微信小程序 + nodeJs(loopback) 实现支付
实现小程序的支付,首先需要去微信官网先了解一下微信小程序支付相关接口文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1
微信支付首先需要调用微信的统一下单接口,返回微信支付接口需要数据。具体参数参考:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
在后端服务中,提供一个小程序前端调用的订单接口,生成预定单并访问微信统一下单接口返回微信接口数据,具体服务端代码如下:
module.exports = (req, res) => {
// TODO replace the codes bellow and add your own codes here
const wx_app_id = server.get('wx-app-id');
let pay_info = {
[wx_app_id]: { // 定义能支付的商户,可能存在多个
mch_id: server.get('wx-mch-id'),
pay_key: server.get('wx-pay-key')
}
}if(!(req.body.appid in pay_info)) {
res.send({
successed: false,
message: '商户不支持支付',
datalist: '暂不支持支付的appid'
});
return
}
let sendtowx = {
appid: req.body.appid,
mch_id: pay_info[req.body.appid].mch_id,
nonce_str: moment().valueOf(),
body: req.body.body,
// detail: req.body.detail,
// attach: req.body.attach,
out_trade_no: getOrderNo(), //订单在同一商家不能重复
total_fee: req.body.total_fee,
spbill_create_ip: req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress,
notify_url: req.body.notify_url, // 订单支付反馈通知接口,一般做修改订单完成状态用,微信支付成功后会在后台调用
trade_type: 'JSAPI',
openid: req.body.openid
}
sendtowx.sign = wx_sign(sendtowx, pay_info[req.body.appid].pay_key); //生成MD5加密字符,传入字段不能有undefined。否则会报签名错误
let request_str = '<xml>'
for (let item in sendtowx) {
request_str = request_str + '<' + item + '>'
request_str = request_str + sendtowx[item]
request_str = request_str + '</' + item + '>'
}
request_str = request_str + '</xml>'
console.log('request_str:', request_str);
const AppOrder = server.models.AppOrder;
AppOrder.findOrCreate({where:req.body.where},{ // 首先创建系统订单,此时状态为待支付
status:"0",
pay_price: sendtowx.total_fee/100,
order_no: sendtowx.out_trade_no
}, function(err, data, created) {
console.log(data,created,'s;s/');
if (err) {
console.log(err);
} else if(created){
console.log("创建预付订单成功",data);
request.post( // 调用微信支付统一下单接口,返回微信预订单数据
{
url : 'https://api.mch.weixin.qq.com/pay/unifiedorder',
// headers: {
// 'Content-Type':'text/xml; charset=utf-8',
// 'Content-Length': data.length
// },
body: request_str,
rejectUnauthorized: false
}, function(err, httpResponse, body){
// 请求完成之后的回调函数
console.log(body)
parseString(body, {explicitArray:false}, function (err, result) {
let res_body = { }
if(result.xml.return_code == 'SUCCESS') {
res_body.successed = true
res_body.message = 'ok'
let temp = {
appId: result.xml.appid,
timeStamp: moment().format('X'),
nonceStr: moment().format('x'),
package: 'prepay_id='+result.xml.prepay_id,
signType: "MD5"
}
temp.paySign = wx_sign(temp, pay_info[result.xml.appid].pay_key)
result.xml = temp
}
else {
res_body.successed = false
res_body.message = '支付失败'
}
if(res_body.message) {
res_body.datalist = result.xml
res.send(res_body);
}
});
})
}
else {
res.send({
code: "applied",
successed: false,
message: '不能重复提交订单!'
});
}
});
}
经常遇到的问题是会报签名错误问题,排查方法:
1.排查微信支付申请的pay-key是否正确,或写成了appid、app-key;
2.排查在上传MD5签名时是否传入了undefined的字段;
3.如果都没问题,建议在微信商户管理后面中重新设置pay-key。
统一下单结束后,小程序前端调用统一下单接口,开始微信支付:
payNow: function (e) {
let that = this;
let data = {
openid: app.globalData.openId,
appid: app.globalData.app_id,
body: this.data.applyGame.name + "测试",
// attach: this.data.applyGame.id,//附加信息,暂时不添加
total_fee: 1,
notify_url: app.globalData.appUrl + 'sdk/wxpayvnotify', // 微信支付成功反馈通知接口
where:{ // 不能重复提交订单条件
status: orderStatus.pay,
}
};
pay(data, (res) => {
if (res.statusCode == 200) {
if (res.data.successed == true) {
let backobj = res.data.datalist;
let timestamp = backobj.timeStamp;
let nonceStr = backobj.nonceStr;
let prepay_id = backobj.package;
let signType = backobj.signType;
let paySign = backobj.paySign;
wx.requestPayment({
'timeStamp': timestamp,
'nonceStr': nonceStr,
'package': prepay_id,
'signType': signType,
'paySign': paySign,
'notify_url': app.globalData.appUrl + 'sdk/wxpayverify',
success: function (res) {
wx.navigateTo({
url: "/pages/my-game/index",
})
wx.switchTab({
url: '/pages/my-game/index',
})
},
fail: function (res) {
console.log(res,'支付失败');
wx.showToast({
title: '支付失败!',
icon: 'none',
})
// wx.navigateTo({
// url: "../pay/payfail/payfail",
// })
},
})
} else {
if (res.data.code === 'applied'){
wx.showToast({
title: '已经报名',
icon: 'none',
})
}else{
wx.showToast({
title: res.data.message,
icon: 'none',
})
}
}
}else{
wx.showToast({
title: '支付失败!',
icon: 'none',
})
}
})
}
支付完成。
微信小程序 + nodeJs(loopback) 实现支付的更多相关文章
- day87_11_7微信小程序之登录,支付(获取ip,requests使用),授权
一.登录接口. 官方文档https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 在登录接口 ...
- 微信小程序对接通联支付
1.首先拿到通联支付开发API:https://aipboss.allinpay.com/know/devhelp/main.php?pid=15#mid=92 2.如果注册通联或者企业认证工作请到: ...
- 让你的微信小程序具有在线支付功能
前言 最近需要在微信小程序中用到在线支付功能,于是看了一下官方的文档,发现要在小程序里实现微信支付还是很方便的,如果你以前开发过服务号下的微信支付,那么你会发现其实小程序里的微信支付和服务号里的开发过 ...
- 微信小程序在线支付功能使用总结
最近需要在微信小程序中用到在线支付功能,于是看了一下官方的文档,发现要在小程序里实现微信支付还是很方便的,如果你以前开发过服务号下的微信支付,那么你会发现其实小程序里的微信支付和服务号里的开发过程如出 ...
- 微信小程序常见问题集合(长期更新)
最新更新: 新手跳坑系列:推荐阅读:<二十四>request:fail错误(含https解决方案)(真机预览问题 跳坑指南<七十>如何让微信小程序服务类目审核通过 跳坑六十九: ...
- 两百条微信小程序跳坑指南(不定时更新)
微信小程序联盟出品 跳坑textarea<二百二十三>不显示文本及textarea相关问题集合跳坑<二百一十三> background-image无法获取本地资源图片....跳 ...
- WordPress版微信小程序开发系列(二):安装使用问答
自WordPress版微信小程序发布开源以来,受关注的程度超过我原来的想象.这套程序主要面对的用户是wordpress网站的站长,如果wordpress站想在微信的生态圈得到推广,小程序成为一种重要的 ...
- nodejs+koa+uniapp实现微信小程序登陆获取用户手机号及openId
nodejs+koa+uniapp实现微信小程序登陆获取用户手机号及openId 前言: 我准备用nodejs+koa+uniapp实现一款餐饮点单小程序,以及nodejs+koa+vue实现后端管理 ...
- 微信小程序-登陆、支付、模板消息
wx.login(OBJECT) 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key).用户数据的加解密通讯需要 ...
随机推荐
- 【1】MySQL大数据量分页查询方法及其优化
---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适应场景: 适用于数据量较少的情况(元组百/千 ...
- IDEA+Maven配置MyBatis的初体验(坑点总结)
起因 在老师的推荐下,我跟着这篇文章https://www.jb51.net/article/70923.htm尝试MyBatis的初次调试运行.途中困难重重,由于教程中的开发环境是eclipse,项 ...
- 转载skbbuf整理笔记
1.http://blog.csdn.net/yuzhihui_no1/article/details/38666589 2.http://blog.csdn.net/yuzhihui_no1/art ...
- Centos7.2下部署Java开发环境
1.安装JDK 如果以前安装过JDK,想要重新安装可执行如下命令进行卸载,这里安装的是JDK1.8: 先查询: rpm -qa|grep jdk 然后再通过下面命令进行卸载 rpm -e --node ...
- java实现多个文件以压缩包导出到本地
描述:使用java将多个文件同时压缩为压缩包,并导出到本地 /** *压缩文件并导出 */ public static void zipFiles() throws IOException { Fil ...
- pythonのdjango 信号
一.内置信号 Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. Model signals pre_init # d ...
- Java位运算原理及使用讲解
前言日常开发中位运算不是很常用,但是巧妙的使用位运算可以大量减少运行开销,优化算法.举个例子,翻转操作比较常见,比如初始值为1,操作一次变为0,再操作一次变为1.可能的做法是使用三木运算符,判断原始值 ...
- STM32 的PWM关闭方法
采用直接修改PWM的占空比,可以实现对PWM的关闭,且切换到稳定的高或者低状态.
- webpack 打包报错:One CLI for webpack must be installed. These are recommended choices, delivered as separate packages
webpack 打包报错: One CLI for webpack must be installed. These are recommended choices, delivered as sep ...
- asp.net core 发布到iis session无法传递的问题
网站是用asp.net core 的Razor Pages开发的,其中用户登录用到了session,调试运行没有问题,但是发布到iis之后出现session无法记录的问题. 我用log记录查看了一下, ...