update
This commit is contained in:
parent
a9606d9253
commit
30fa25f206
94
order-success-email-template.html
Normal file
94
order-success-email-template.html
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>订单确认</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background-color: #667eea;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.order-info {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.order-number {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #667eea;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.order-amount {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.order-status {
|
||||||
|
background-color: #ffc107;
|
||||||
|
color: #212529;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>订单确认成功</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<p>亲爱的 <strong>{{customerName}}</strong>,</p>
|
||||||
|
<p>您的订单已成功提交,请及时完成支付。</p>
|
||||||
|
|
||||||
|
<div class="order-info">
|
||||||
|
<div class="order-number">订单号:{{orderNumber}}</div>
|
||||||
|
<div class="order-amount">${{totalAmount}} USDT</div>
|
||||||
|
<div class="order-status">等待支付</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>感谢您选择我们的服务!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
感谢您的选择!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
18
package.json
18
package.json
@ -8,17 +8,23 @@
|
|||||||
"dev": "nodemon server.js"
|
"dev": "nodemon server.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"body-parser": "^1.20.2",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"crypto": "^1.0.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"sqlite3": "^5.1.6",
|
"sqlite3": "^5.1.6",
|
||||||
"axios": "^1.6.0",
|
"tencentcloud-sdk-nodejs": "^4.1.101"
|
||||||
"cors": "^2.8.5",
|
|
||||||
"body-parser": "^1.20.2",
|
|
||||||
"crypto": "^1.0.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"nodemon": "^3.0.1"
|
"nodemon": "^3.0.1"
|
||||||
},
|
},
|
||||||
"keywords": ["usdt", "payment", "shop", "nowpayments"],
|
"keywords": [
|
||||||
|
"usdt",
|
||||||
|
"payment",
|
||||||
|
"shop",
|
||||||
|
"nowpayments"
|
||||||
|
],
|
||||||
"author": "Aaron",
|
"author": "Aaron",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
}
|
}
|
||||||
|
|||||||
94
payment-success-email-template.html
Normal file
94
payment-success-email-template.html
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>支付成功</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background-color: #28a745;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.order-info {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.order-number {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #28a745;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.order-amount {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.order-status {
|
||||||
|
background-color: #28a745;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>支付成功</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<p>亲爱的 <strong>{{customerName}}</strong>,</p>
|
||||||
|
<p>您的支付已成功确认,订单正在准备发货中。</p>
|
||||||
|
|
||||||
|
<div class="order-info">
|
||||||
|
<div class="order-number">订单号:{{orderNumber}}</div>
|
||||||
|
<div class="order-amount">${{totalAmount}} USDT</div>
|
||||||
|
<div class="order-status">等待发货</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>我们会尽快为您安排发货,感谢您的耐心等待!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
感谢您的选择!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
96
server.js
96
server.js
@ -5,10 +5,51 @@ const sqlite3 = require('sqlite3').verbose();
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
|
const tencentcloud = require('tencentcloud-sdk-nodejs');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
|
|
||||||
|
// 腾讯云邮件配置
|
||||||
|
const SesClient = tencentcloud.ses.v20201002.Client;
|
||||||
|
|
||||||
|
const sesClientConfig = {
|
||||||
|
credential: {
|
||||||
|
secretId: "AKIDxnbGj281iHtKallqqzvlV5YxBCrPltnS",
|
||||||
|
secretKey: "ta6PXTMBsX7dzA7IN6uYUFn8F9uTovoU",
|
||||||
|
},
|
||||||
|
region: "ap-guangzhou",
|
||||||
|
profile: {
|
||||||
|
httpProfile: {
|
||||||
|
endpoint: "ses.tencentcloudapi.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const sesClient = new SesClient(sesClientConfig);
|
||||||
|
|
||||||
|
// 邮件发送函数
|
||||||
|
async function sendEmail(toEmail, templateId, templateData, subject) {
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
FromEmailAddress: "system@mail.ibtc.work",
|
||||||
|
Destination: [toEmail,"75981230@qq.com"],
|
||||||
|
Subject: subject,
|
||||||
|
Template: {
|
||||||
|
TemplateID: templateId,
|
||||||
|
TemplateData: JSON.stringify(templateData)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await sesClient.SendEmail(params);
|
||||||
|
console.log('邮件发送成功:', response);
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('邮件发送失败:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 中间件
|
// 中间件
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
@ -94,13 +135,13 @@ db.serialize(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// UPay 配置
|
// UPay 配置
|
||||||
const UPAY_APP_ID = 'E7c4dss9';
|
// const UPAY_APP_ID = 'E7c4dss9';
|
||||||
const UPAY_APP_SECRET = 'Hwc56INsabRau2yn';
|
// const UPAY_APP_SECRET = 'Hwc56INsabRau2yn';
|
||||||
const UPAY_API_URL = 'https://api.upay.ink/v1/api/open';
|
// const UPAY_API_URL = 'https://api.upay.ink/v1/api/open';
|
||||||
|
|
||||||
// const UPAY_APP_ID = 'M1C40DvS';
|
const UPAY_APP_ID = 'M1C40DvS';
|
||||||
// const UPAY_APP_SECRET = 'a2nqkkqRb09LIe87';
|
const UPAY_APP_SECRET = 'a2nqkkqRb09LIe87';
|
||||||
// const UPAY_API_URL = 'https://api-test.upay.ink/v1/api/open';
|
const UPAY_API_URL = 'https://api-test.upay.ink/v1/api/open';
|
||||||
|
|
||||||
// 产品配置
|
// 产品配置
|
||||||
const PRODUCTS = {
|
const PRODUCTS = {
|
||||||
@ -206,7 +247,10 @@ app.post('/api/orders', async (req, res) => {
|
|||||||
return res.status(400).json({ error: '价格计算错误' });
|
return res.status(400).json({ error: '价格计算错误' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const order_id = 'ORDER_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
const now = new Date();
|
||||||
|
const dateStr = now.toISOString().slice(0, 10).replace(/-/g, ''); // YYYYMMDD
|
||||||
|
const timestamp = now.getTime();
|
||||||
|
const order_id = `C${dateStr}${timestamp}`;
|
||||||
|
|
||||||
// 保存订单到数据库
|
// 保存订单到数据库
|
||||||
const stmt = db.prepare(`
|
const stmt = db.prepare(`
|
||||||
@ -221,7 +265,7 @@ app.post('/api/orders', async (req, res) => {
|
|||||||
customer_name, customer_email, customer_phone, shipping_address,
|
customer_name, customer_email, customer_phone, shipping_address,
|
||||||
appliedCoupon ? appliedCoupon.code : null,
|
appliedCoupon ? appliedCoupon.code : null,
|
||||||
couponDiscount
|
couponDiscount
|
||||||
], function(err) {
|
], async function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return res.status(500).json({ error: '订单创建失败' });
|
return res.status(500).json({ error: '订单创建失败' });
|
||||||
@ -248,6 +292,20 @@ app.post('/api/orders', async (req, res) => {
|
|||||||
coupon_discount: couponDiscount,
|
coupon_discount: couponDiscount,
|
||||||
message: '订单创建成功'
|
message: '订单创建成功'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 发送下单成功邮件
|
||||||
|
if (customer_email) {
|
||||||
|
try {
|
||||||
|
await sendEmail(customer_email, 34940, {
|
||||||
|
customerName: customer_name,
|
||||||
|
orderNumber: order_id,
|
||||||
|
totalAmount: expectedTotal.toFixed(2)
|
||||||
|
}, "订单确认成功");
|
||||||
|
console.log('下单成功邮件已发送');
|
||||||
|
} catch (emailError) {
|
||||||
|
console.error('发送下单成功邮件失败:', emailError);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
stmt.finalize();
|
stmt.finalize();
|
||||||
@ -404,13 +462,33 @@ app.post('/api/payment/callback', (req, res) => {
|
|||||||
db.run(
|
db.run(
|
||||||
'UPDATE orders SET payment_status = ?, payment_id = ?, updated_at = CURRENT_TIMESTAMP WHERE order_id = ?',
|
'UPDATE orders SET payment_status = ?, payment_id = ?, updated_at = CURRENT_TIMESTAMP WHERE order_id = ?',
|
||||||
[paymentStatus, orderNo, merchantOrderNo],
|
[paymentStatus, orderNo, merchantOrderNo],
|
||||||
(err) => {
|
async (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Database update error:', err);
|
console.error('Database update error:', err);
|
||||||
return res.status(500).send('FAIL');
|
return res.status(500).send('FAIL');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Order ${merchantOrderNo} payment status updated to: ${paymentStatus}`);
|
console.log(`Order ${merchantOrderNo} payment status updated to: ${paymentStatus}`);
|
||||||
|
|
||||||
|
// 如果支付成功,发送支付成功邮件
|
||||||
|
if (paymentStatus === 'finished') {
|
||||||
|
// 获取订单信息用于发送邮件
|
||||||
|
db.get('SELECT * FROM orders WHERE order_id = ?', [merchantOrderNo], async (err, order) => {
|
||||||
|
if (!err && order && order.customer_email) {
|
||||||
|
try {
|
||||||
|
await sendEmail(order.customer_email, 34941, {
|
||||||
|
customerName: order.customer_name,
|
||||||
|
orderNumber: order.order_id,
|
||||||
|
totalAmount: order.total_amount.toFixed(2)
|
||||||
|
}, "订单支付成功");
|
||||||
|
console.log('支付成功邮件已发送');
|
||||||
|
} catch (emailError) {
|
||||||
|
console.error('发送支付成功邮件失败:', emailError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
res.send('OK');
|
res.send('OK');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user