微信小程序 + 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).用户数据的加解密通讯需要 ...
随机推荐
- 适用于单片机的数据加密算法:xxtea
转:https://www.cnblogs.com/LittleTiger/p/4384741.html 各位大侠在做数据传输时,有没有考虑过把数据加密起来进行传输,若在串口或者无线中把所要传的数据加 ...
- npm knowledge basics
npm inro https://www.npmjs.com/ npm is the package manager for javascript npm 为 nodejs默认的包管理工具, 为nod ...
- Koa与Node.js开发实战(3)——Nunjucks模板在Koa中的应用(视频演示)
技术架构: 在Koa中应用Nunjucks,需要先把Nunjucks集成为符合Koa规格的中间件(Middleware),从本质上来讲,集成后的中间件的作用是给上下文对象绑定一个render(vi ...
- Swagger UI及 Swagger editor教程 API文档搭配 Node使用
swagger ui 是一个在线文档生成和测试的利器,目前发现最好用的.为啥好用呢?打开 demo,支持API自动生成同步的在线文档些文档可用于项目内部API审核方便测试人员了解 API这些文档可作为 ...
- SVN的安装与使用教程
转载:http://www.cnblogs.com/armyfai/p/3985660.html SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很多不同的版本,这就需 ...
- istio环境搭建for macbook
首先需要搭建docker+k8s环境,如何搭建这里就不再赘述,可以自行搜索. 打开命令行,运行命令: curl -L https://git.io/getLatestIstio | ISTIO_VER ...
- mysql并发控制之数据库锁
1.mysql和redis的区别 mysql是一种关系型数据库,数据会最终存储在磁盘上.而redis是一种非关系型的nosql数据库,以key-value的形式存储数据,将数据存储在内存.从性能上来说 ...
- vue内置的标签(组件)
component:用于动态组件,查看博文vue学习之组件. <component :is="componentId"></component> trans ...
- dubbo注册中心
官方推荐的是zookeeper注册中心. 1.Multicast 注册中心 Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现. 提供方启动时广播自己的地址消费方启动 ...
- 【译】索引进阶(十一):SQL SERVER中的索引碎片【上篇】
原文链接:传送门. 第十章节我们分析了索引的内部结构.有了这些关于索引结构的知识,我们便可以分析索引碎片了:其产生的原因,如何防止,以及何时可以不去关注它们. 一些背景知识 / 复习 以下知识对于理解 ...