在Node.js项目中部署越南支付网关插件
要在Node.js项目中集成越南支付网关,您可以按照以下步骤操作:
1. 选择适合的越南支付网关
常见的越南支付网关包括:
- MoMo
- VNPay
- ZaloPay
- OnePay
- Payoo
2. 安装必要的依赖包
npm install axios crypto querystring --save
3. VNPay集成示例代码
const crypto = require('crypto');
const querystring = require('querystring');
const axios = require('axios');
class VNPayment {
constructor(config) {
this.vnp_TmnCode = config.vnp_TmnCode;
this.vnp_HashSecret = config.vnp_HashSecret;
this.vnp_Url = config.vnp_Url || 'https://sandbox.vnpayment.vn/paymentv2/vpcpay.html';
this.returnUrl = config.returnUrl;
}
createPayment(orderInfo, amount, orderId, ipAddr) {
const dateFormat = require('dateformat');
let vnp_Params = {};
vnp_Params['vnp_Version'] = '2.1.0';
vnp_Params['vnp_Command'] = 'pay';
vmp_Params['vmp_TmnCode']=this.tmnCode;
// ...其他参数设置...
// Secure hash生成
const signData=querystring.stringify(vmpParams,'','&');
return `${this.url}?${signData}&vmp_SecureHash=${secureHash}`;
}
}
//使用示例:
const payment=newVNPayment({
tmncode:"YOURTMNCODE",
secretKey:"YOURSECRETKEY",
url:"https://sandbox...",//测试环境URL
returnurl:"http://yourdomain.com/return"
});
router.post('/create-payment',(req,res)=>{
const{amount}=req.body;
const paymentUrl=payment.createPayment(
"Thanh toan don hang",//订单描述
amount*100,//金额(VND)
Date.now(),//订单ID
req.ip //客户IP地址
);
res.json({payment_url:paymentUrl});
});
4.MoMo集成示例代码
class MomoPayment{
constructor(config){
this.partnerCode=config.partnerCode||'MOMO';
this.accessKey=config.accessKey;
this.secretkey=config.secretkey;
}
async createRequest(amount){
try{
let rawSignature=`partnerCode=${this.partnerCode}&accessKey=${this.accessKey}
&requestId=${Date.now()}&amount=${amount}
&orderId=MOMO${Date.now()}`;
//创建签名...
return await axios.post("https://test-payment.momo...",requestBody);
}catch(err){
console.error(err);
throw err;
}
}
}
5.ZaloPay集成示例
class ZaloPayService{
constructor(appid,key1){/*...*/}
async createOrder(params){
/*Zalo特有逻辑*/
}
}
最佳实践建议:
1.环境配置:
-为开发/生产环境使用不同配置
2.错误处理:
try{/*调用API*/}catch(e){logError(e)}
3.日志记录:记录所有交易请求和响应
4.安全考虑:
-不要在前端暴露密钥等敏感信息
5.Webhook处理:实现回调验证逻辑
需要针对特定支付网关的更详细实现或有任何问题请随时询问!
继续深入Node.js集成越南支付网关
下面我将更详细地介绍如何完善支付网关集成,包括回调处理、安全验证和最佳实践。
6. 完善VNPay回调处理
// vnpay.service.js
class VNPayment {
// ...之前的代码...
verifyReturn(query) {
const vnp_Params = {...query};
const secureHash = vnp_Params['vnp_SecureHash'];
delete vnp_Params['vnp_SecureHash'];
delete vnp_Params['vnp_SecureHashType'];
// 按字母顺序排序参数
const sortedParams = this.sortObject(vmp_Params);
// 生成校验签名
const signData = querystring.stringify(sortedParams, '', '&');
const hmac = crypto.createHmac('sha512', this.vmp_HashSecret);
const signed = hmac.update(Buffer.from(signData, 'utf-8')).digest('hex');
return secureHash === signed;
}
sortObject(obj) {
return Object.keys(obj).sort().reduce((result, key) => {
result[key] = obj[key];
return result;
}, {});
}
}
// callback.controller.js
router.get('/vnpay-return', (req, res) => {
try{
if(!payment.verifyReturn(req.query)){
return res.status(400).send('Invalid signature');
}
// TODO:更新订单状态逻辑...
if(req.query.vmp_ResponseCode === '00'){
res.send('Payment success!');
}else{
res.send(`Payment failed: ${req.query.vmp_ResponseMessage}`);
}
}catch(e){
console.error(e);
res.status(500).send('Server error');
}
});
7.MoMoWebhook处理示例
// momo.webhook.js
router.post('/momo-callback',express.json(),async(req,res)=>{
try{
/*1.验证签名*/
/*2.检查交易状态*/
/*3.更新数据库*/
}catch(err){/*错误处理*/}
});
function verifySignature(rawSignature,signature){
/*使用secretKey验证HMAC SHA256签名*/
}
8.ZaloPayIPN处理器
constzalopayIPN=async(orderId)=>{
/*1.调用ZaloAPI查询订单状态*/
/*2.与本地记录比对*/
/*3.resolve/rejectpromise*/
}
高级配置建议:
9.RateLimiting:防止暴力攻击
app.use('/payment-api',rateLimit({
windowMs:15*60*1000,
max:100//每个IP限制请求数
}));
10.DatabaseIntegration:存储交易记录模型示例(Mongoose)
const paymentSchema=new mongoose.Schema({
gateway:{type:String},//"VNPAY/MOMO"
amount:{type:Number},
status:{type:String},//pending/success/failed
transactionId:{type:String},
createdAt:{type:Date}
});
const Payment=mongoose.model("Payment",paymentSchema);
async function saveTransaction(paymentData){
await Payment.create(paymentData);
}
11.TestingStrategy:模拟支付流程的测试用例
it("should generate valid payment URL",()=>{...})
it("should detect tampered callback",()=>{...})
})
需要我针对某个特定部分如:
-某个网关的完整SDK封装?
-与前端Vue/React的交互示例? -性能优化技巧?
请告诉我您的具体需求方向。
# 深入支付网关集成的进阶实现
下面我将提供更完整的SDK封装、前端交互方案和性能优化策略,帮助您构建生产级支付解决方案。
12. 完整VNPay SDK封装示例
“`javascript
// lib/vnpay.js
const crypto = require(‘crypto’);
const querystring = require(‘querystring’);
class VNPaySDK {
constructor(config) {
this.validateConfig(config);
this.config = {
tmnCode: config.tmnCode,
secretKey: config.secretKey,
returnUrl: config.returnUrl,
apiUrl: config.apiUrl || ‘https://sandbox.vnpayment.vn’,
currency: config.currency || ‘VND’,
locale: config.locale || ‘vn’
};
this.logger = config.logger || console;
}
validateConfig(config) {
if (!config.tmnCode || !config.secretKey) {
throw new Error(‘Missing required configuration (tmnCode, secretKey)’);
}
}
async createPayment(orderData) {
const { orderId, amount, description, clientIp } = orderData;
const paymentParams = {
vnp_Version: ‘2.1.0’,
vnp_Command: ‘pay’,
vnp_TmnCode: this.config.tmnCode,
vnp_Amount: Math.round(amount * 100), // Convert to cents
vnp_CreateDate: new Date().toISOString().replace(/[-T:.Z]/g, ”),
// …其他参数…
return `${this.getPaymentUrl()}?${queryString}&vnp_SecureHash=${secureHash}`;
}
getPaymentStatus(params){
/*调用VNPay查询API*/
}
}
module.exports = VNPaySDK;
“`
13.React前端集成示例
“`jsx
// PaymentButton.jsx
import axios from’axios’;
export default function PaymentButton({amount}){
const handlePayment=async()=>{
try{
const res=await axios.post(‘/api/payments’,{
gateway:’vnpay’,
amount
});
window.location.href=res.data.payment_url;
}catch(err){/*错误处理*/}
};
return
}
“`
14.Vue3组合式API集成
“`vue
“`
高级安全措施:
15.SensitiveDataProtection
“`js
//使用环境变量加密存储密钥(vault.js)
const vault={
get(key){
return decrypt(process.env[`PAYMENT_${key}`]);
}
};
//在控制器中:
const secret=vault.get(‘VNPAY_SECRET’);
“`
16.RequestValidationMiddleware
“`js
function validateCreateRequest(req,res,next){
Joi.object({
amountJoi.number().min(1000).required(), //最小10k VND
}).validateAsync(req.body)
.then(()=>next())
.catch(next); //传递到错误处理器
app.post(‘/payments’,validateCreateRequest,(req.res)=>{});
“`
性能优化技巧:
17.CachingFrequentQueries
“`js
const NodeCache=require(“node-cache”);
const gatewayCache=new NodeCache({stdTTL600});
async function getGatewayStatus(gatewayId){
if(gatewayCache.has(gatewayId)){
return gatewayCache.get(gatewayId);
}
const status=await fetchRemoteStatus();
gatewayCache.set(gatewayIdstatus);
return status;
}
“`
需要我继续展开哪个方面的内容?例如:
-具体某个支付网关的完整业务流程?
-与AWS/GCP云服务的整合方案?
-高并发场景下的处理策略?
-PCI DSS合规性建议?
