微信支付是腾讯集团旗下的第三方支付平台,致力于为用户和企业提供安全、便捷、专业的在线支付服务。以“微信支付,不止支付”为核心理念,为个人用户创造了多种便民服务和应用场景。微信支付为各类企业以及小微商户提供专业的收款能力,运营能力,资金结算解决方案,以及安全保障。用户可以使用微信支付来购物、吃饭、旅游、就医、交水电费等。企业、商品、门店、用户已经通过微信连在了一起,让智慧生活,变成了现实。
小程序实现微信支付主要有两种方式:
微信支付开发文档V2、V3选择: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/api.shtml
微信小程序调用微信支付接口需要5个参数都是来源于后端接口生成的
wx.requestPayment({
timeStamp: payArgs.timeStamp,
nonceStr: payArgs.nonceStr,
package: payArgs. package,
signType:'MD5',
paySign: payArgs. paySign
})
小程序ID(appld) 时间戳(timeStamp)当前的时间,从1970年1月1日00:00:00至今的秒数 随机串(nonceStr) 一个32位的随机字符串 数据包(package) prepay_id=wx2017033010242291fcfe0db70013231072 签名方式(signType)默认为MD5,也有其它支持的类型 签名字符串(paySign)
node安装相关依赖
router .js
npm install koa3-wechat
npm install short-uuid
npm i raw-body
npm i redis
npm i babel-runtime@6.26.0
在路由模块中引入支付模块
const Pay = require("./pay")
const Router = require("@koa/router")
const router = new Router({
prefix: '/user'
});
Pay.init(router)
module.exports = router
pay.js
const { wepay: WechatPay } = require('koa3-wechat');
const short = require('short-uuid');
// const fs = require('fs');
const wepay = require("../lib/wepay")
const Order = require("../models/order-model")
const wepay2 = require('../lib/wepay2')
function init(router) {
// post /user/my/order
// 下新定单,准备支付
router.post('/my/order', async ctx => {
let { uid: userId, openId } = ctx.user
let { totalFee, addressId, addressDesc, goodsCartsIds, goodsNameDesc } = ctx.request.body
// 为测试方便,所有金额支付数均为1分
totalFee = 1
let payState = 0
// 依照Order模型接收参数
let outTradeNo = `${new Date().getFullYear()}${short().new()}`
// 获取订单的预支付信息
var trade = {
body: goodsNameDesc.substr(0, 127), //最长127字节
attach: '支付测试', //最长127字节
out_trade_no: outTradeNo, //
total_fee: totalFee, //以分为单位,货币的最小金额
trade_type: 'JSAPI',//NATIVE
spbill_create_ip: ctx.request.ip, //ctx.request.ip
openid: openId
};
var params = await wepay.getBrandWCPayRequestParams(trade);
let err = '', res
if (params && params.package && params.paySign) {
// 创建记录
res = await Order.create({
userId,
outTradeNo,
payState,
totalFee,
addressId,
addressDesc,
goodsCartsIds,
goodsNameDesc
})
if (!res) err = 'db create error'
} else {
err = 'error! return null!'
console.log(err);
}
ctx.status = 200
ctx.body = {
code: 200,
msg: !err ? 'ok' : '',
data: {
res,
params
}
}
})
// post /user/my/order2
// 使用weixin-pay实现的接口,测试通过
router.post('/my/order2', async ctx => {
let { uid: userId, openId } = ctx.user
let { totalFee, addressId, addressDesc, goodsCartsIds, goodsNameDesc } = ctx.request.body
// 为测试方便,所有金额支付数均为1分
totalFee = 1
let payState = 0
// 依照Order模型接收参数
let outTradeNo = `${new Date().getFullYear()}${short().new()}`
console.log('outTradeNo', outTradeNo);
// 获取订单的预支付信息
var trade = {
body: goodsNameDesc.substr(0, 127), //最长127字节
out_trade_no: outTradeNo, //
total_fee: totalFee, //以分为单位,货币的最小金额
spbill_create_ip: ctx.request.ip, //ctx.request.ip
notify_url: 'https://rxyk.cn/apis/pay_notify', // 支付成功通知地址
trade_type: 'JSAPI',
openid: openId
};
let params = await (() => {
return new Promise((resolve, reject) => {
wepay2.getBrandWCPayRequestParams(trade, (err, result) => {
console.log(err, result);
if (err) reject(err)
else resolve(result)
});
})
})()
let err = '', res
if (params && params.package && params.paySign) {
// 创建记录
res = await Order.create({
userId,
outTradeNo,
payState,
totalFee,
addressId,
addressDesc,
goodsCartsIds,
goodsNameDesc
})
if (!res) err = 'db create error'
} else {
err = 'error! getBrandWCPayRequestParams() return null!'
console.log(err);
}
ctx.status = 200
ctx.body = {
code: 200,
msg: !err ? 'ok' : '',
data: {
res,
params
}
}
})
}
module.exports = {
init
}
order.js
const DataTypes = require('sequelize')
const db = require("./mysql-db")
module.exports = db.define("order",{
id:{
type:DataTypes.INTEGER(11),
allowNull:false,
primaryKey:true,
autoIncrement:true
},
userId:{
type:DataTypes.INTEGER(20),
allowNull:false
},
outTradeNo:{// 微信商号单号
type:DataTypes.STRING(50),
allowNull:false
},
transactionId:{// 微信交易单号
type:DataTypes.STRING(50),
allowNull:true //允许为空
},
payState:{// 支付订单的状态,0=未支付,1=已支付,2=取消或其它
type:DataTypes.INTEGER,
defaultValue:0,
allowNull: false
},
totalFee:{//总价,单位分
type:DataTypes.INTEGER(11),
allowNull:false
},
addressId:{//收货地址id
type:DataTypes.INTEGER(20),
allowNull:false
},
addressDesc:{//收货地址总描述
type:DataTypes.TEXT('tiny'),//最大长度255个字节
allowNull:false
},
goodsCartsIds:{//购买车商品ids
type:DataTypes.JSON,
allowNull:false
},
goodsNameDesc:{//商品名称描述
type:DataTypes.TEXT('tiny'),//最大长度255个字节
allowNull:false
}
},{
indexes: [{
unique: true,// 唯一索引
fields: ['out_trade_no']
}],
underscored: true,
freezeTableName:true,
timestamps:true
});
wepay.js
const {wepay:WechatPay} = require('koa3-wechat');
// const short = require('short-uuid');
const fs = require('fs');
// 普通商户的参数
let config = {
appId: '自己的APPID', // 小程序APPID
mchId: '自己的商户id',//商户id
notifyUrl: '自己的通知地址', // 支付成功通知地址
partnerKey: '自己的api key', // 微信商户平台的api key,在pay.weixin.qq.com设置
pfx: fs.readFileSync(__dirname + '/apiclient_cert.p12'),
// passphrase: '预留信息',// 添加了无法退款
}
// 初始化
let wepay = new WechatPay(config);
module.exports = wepay
wepay2.js
const WXPay = require('weixin-pay')
// const short = require('short-uuid')
const fs = require('fs')
const wxpay2 = WXPay({
appid: "自己的APPID",//小程序APPID
mch_id: '自己的商户id',//商户id
notify_url: '自己的通知地址', // 支付成功通知地址
partnerKey: '自己的api key', // 微信商户平台的api key,在 API secret,非小程序 secret
pfx: fs.readFileSync(__dirname + '/apiclient_cert.p12'),
passphrase: '预留信息'
});
module.exports = wxpay2