# egg-wxpay
**Repository Path**: iteming/egg-wxpay
## Basic Information
- **Project Name**: egg-wxpay
- **Description**: nodejs egg框架,微信支付sdk
- **Primary Language**: NodeJS
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 13
- **Forks**: 4
- **Created**: 2019-03-13
- **Last Updated**: 2024-01-19
## Categories & Tags
**Categories**: payment-dev
**Tags**: None
## README
# egg-wxpay
#### 介绍
nodejs egg框架,微信支付sdk
# 微信支付demo示例
微信支付nodejs demo
### 开发步骤
##### 1. 引入扩展包
###### 1.1 app/extend/util.js (常用工具类库)
###### 1.2 app/extend/wxpay.js (微信支付类库)
##### 2. packages.json 添加 微信支付依赖包
```
"dependencies": {
"MD5": "^1.2.1",
"request": "^2.88.0",
"body-parser": "^1.18.3",
"xml2js": "^0.4.6"
},
```
##### 3. mpn install 导入依赖包
##### 4. 在要使用的文件里,添加微信支付声明 app/controller/home.js
```
//引入微信支付插件 (注意插件路径和文件路径)
const WXPay = require('../extend/wxpay');
const fs = require('fs');
const wxpay = WXPay({
appid: '公众号ID',
mch_id: '商户号ID',
partner_key: '商户密钥(证书密码)',
pfx: fs.readFileSync('././证书路径.p12'),
});
```
##### 5. 在要使用的方法里,进行调用
##### 5.1 创建扫码支付(非固定二维码,统一下单接口)
```
const result = await wxpay.createUnifiedOrder({
body: '扫码支付测试', // 商品描述
out_trade_no: ctx.request.body.orderNum, //订单编号
total_fee: 1, //支付总金额(单位:分)
spbill_create_ip: '192.168.2.210', //付款ip
notify_url: 'http://mp.ngrok.xiaomiqiu.cn/receive/wxReceive',//支付回调地址
trade_type: 'NATIVE',//支付方式 扫码付
});
console.log(result);
ctx.status = 200;
// 处理表单提交后的事件,此处返回表单提交的内容
ctx.body = `${JSON.stringify(result)}`;
```
##### 5.2 创建公众号支付(JSAPI,小程序支付相同)
```
//后台调用
const result = await wxpay.getBrandWCPayRequestParams({
openid: 'om5QFwFZ15e60lUej4uHN5-DGn8Y', //微信用户openid
body: '公众号支付测试', //支付内容
detail: '公众号支付测试',//支付内容
out_trade_no: ctx.request.body.orderNum, //订单编号
total_fee: 1, //支付总金额(单位:分)
spbill_create_ip: '192.168.2.210',
notify_url: 'http://mp.ngrok.xiaomiqiu.cn/receive/wxReceive',//支付回调地址
});
console.log(result);
// 渲染静态页面,模拟提交表单
await ctx.render('home/jsapiresult', { payargs: `${JSON.stringify(result)}` });
//网页调用参数(以nunjucks为例)
```
##### 5.2 创建H5支付(MWEB)
```
const result = await wxpay.createOutH5Pay({
body: 'H5支付测试', // 商品描述
out_trade_no: ctx.request.body.orderNum, //订单编号
total_fee: 1, //支付总金额(单位:分)
spbill_create_ip: '192.168.2.210', //付款ip
notify_url: 'http://mp.ngrok.xiaomiqiu.cn/receive/wxReceive',//支付回调地址
trade_type: 'NATIVE',//支付方式 扫码付
});
if (result.return_code == "SUCCESS") {
// 渲染静态页面,模拟提交表单
// 此处需要添加支付完成或取消返回的路径
result.mweb_url = result.mweb_url + "&redirect_url=" + urlencode("http://mp.ngrok.xiaomiqiu.cn/h5pay")
}
console.log(result);
ctx.status = 200;
// 处理表单提交后的事件,此处返回表单提交的内容
ctx.body = `${JSON.stringify(result)}`;
```
##### 5.4 通过商户订单号查询支付结果
```
const result = await wxpay.queryOrder({
out_trade_no: ctx.request.body.orderNum, //订单编号
});
ctx.status = 200;
// 处理表单提交后的事件,此处返回表单提交的内容
ctx.body = `${JSON.stringify(result)}`;
```
##### 5.5 通过商户订单号进行订单退款
```
wxpay.refundOrder({
out_trade_no: 'API2019010100001003',
total_fee: 1,
refund_fee: 1,
notify_url: 'http://mp.ngrok.xiaomiqiu.cn/receive/wxRefund',
out_refund_no: 'RFD2019010100001002'
}, function(err, result){
console.log(result);
});
```
#### 6 回调功能
##### 6.1 服务端处理微信的回调(express为例)
```
// 6.1 支付结果异步通知
app.use('/receive/wxReceive', wxpay.useWXCallback(function(msg, req, res, next){
// 处理商户业务逻辑
// res.success() 向微信返回处理成功信息,res.fail()返回失败信息。
console.log("收到支付回调");
console.log(msg);
console.log(req);
console.log(res);
res.success();
}));
6.2 退款回调同支付回调。
```
##### 6.2 服务端处理微信的回调(egg为例)
```
6.2.1 首先添加中间件 app/middleware/xmlparse.js
6.2.2 然后启用中间件 config/config.default.js
添加: exports.middleware = ['xmlparse'];
6.2.3 路由中配置中间件 app/router.js
const {router, controller, middleware} = app;
router.post('/receive/wxReceive', middleware.xmlparse(), controller.home.wxReceive);
6.2.4 然后就可以在 app/controller/home.js 里写收到回调的处理了
async wxReceive() {
const { ctx } = this;
console.log("收到支付回调 out");
// 支付结果异步通知
wxpay.eggWXCallback(ctx.req, ctx.res, function(msg, req, res){
console.log("收到支付回调");
console.log(msg);
res.success();
});
}
6.2.5 退款回调同支付回调。
```
#### 遇到的问题:
##### 1.request 请求总是失败:报错说不认识 toString()
```
问题原因:证书路径.p12 是一个空的,需要使用真实证书和对应的 微信支付key mch_id app_id等。
```
##### 2.支付回调请求总是无法解析,报错 stream.on 不是一个 action
```
问题原因:
2.1 没有使用中间件,xmlparse.js
2.2 没有使用接收到的 this.ctx.req 传入 wxpay.js 里做处理(问题已修复)。
```
##### 3.接收支付回调的时候,会报一个 missing csrf token. See https://eggjs.org/zh-cn/core/security.html#安全威胁
```
// 解决方案:需要在 config/config.default.js 中关闭CSRF校验 (默认的 egg-security 插件对以上三种 非安全方法 进行了 CSRF 校验)
exports.security = {
csrf: false,
};
```
#### 码云特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)