通过下单获取prepay_id,然后返回给小程序发起支付
若是服务商,mch_id:传入服务的商户号;sub_mch_id:传入子商户的商户号,算法签名的秘钥是服务商的秘钥。
'use strict';
const Service = require('egg').Service;
class wxPayment extends Service {
// 小程序支付
async unifiedorder(data) {
const { ctx } = this;
const wxpayUitls = ctx.service.payment.helper.paymentUitls;
// 微信支付调用ip
const ip = ctx.request.ip.replace(/::ffff:/, '');
const params = {
// 小程序appid
appid: this.config.wxampPayConfig.appid,
// 商户号
mch_id: this.config.wechatPayConfig.mch_id,
// 子商户号
sub_mch_id: this.config.wechatPayConfig.sub_mch_id,
// 32位以内随机字符串
nonce_str: wxpayUitls.createNonceStr(),
// 商品描述
body: data.body,
// 商户订单号,32个字符内
out_trade_no: wxpayUitls.getTradeNo(),
// 金额,分;正式上线时启用
// total_fee: wxpayUitls.regYuanToFen(data.total, 100),
total_fee: 1,
// 终端ip
spbill_create_ip: ip,
// 通知地址
notify_url: 'http://baidu.com',
// 交易类型
trade_type: 'JSAPI',
// 用户标识
openid: data.openID,
};
// 算法签名,传入参数及服务商商户的秘钥
params.sign = wxpayUitls.getSign(params, this.config.wechatPayConfig.wxPaykey);
const url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
const res = await ctx.curl(url, {
method: 'POST',
dataType: 'text/xml', // 注意接口数据类型
data: wxpayUitls.createXML(params), // 动态生成的xml
});
const result = await wxpayUitls.parserXML(res.data.toString());
// 返回的参数
const r = {
appId: this.config.wxampPayConfig.appid, // 当前小程序的appid
timeStamp: wxpayUitls.createTimeStamp(), // 注意类型String
nonceStr: result.xml.nonce_str,
package: 'prepay_id=' + result.xml.prepay_id,
signType: 'MD5',
};
r.paySign = wxpayUitls.getSign(r, this.config.wechatPayConfig.wxPaykey);
r.tradeNo = params.out_trade_no;
return r;
}
}
module.exports = wxPayment;
helper.js
'use strict';
// eslint-disable-next-line strict
const QueryString = require('querystring');
const Crypto = require('crypto');
const XmlToJs = require('xml2js');
exports.paymentUitls = {
// 订单号
getTradeNo: () => {
let No = '';
for (let i = 0; i < 5; i++) {
No += Math.floor(Math.random() * 10);
}
No = new Date().getTime() + No;
return No;
},
/**
* 元的转化
* @param yuan {number} 金额
* @param digit {number} 放大倍数,如果元转分则为100
* */
regYuanToFen(yuan, digit) {
let m = 0;
const s1 = yuan.toString();
const s2 = digit.toString();
try {
m += s1.split('.')[1].length;
m += s2.split('.')[1].length;
} catch (e) {
// console.log(e);
}
return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m);
},
// 时间戳产生函数
createTimeStamp() {
return parseInt(new Date().getTime() / 1000) + '';
},
// 生成随机的NonceStr,随机字符串,不长于32位。
createNonceStr: () => {
return Math.random()
.toString(36)
.substr(2, 15);
},
// 获取微信支付的签名
/**
* @param signParams {object} 请求参数的集合
* @param key {string} 商户号
* */
getSign: (signParams, key) => {
// 按 key 值的ascll 排序
let keys = Object.keys(signParams);
keys = keys.sort();
const newArguments = {};
// eslint-disable-next-line no-unused-vars
keys.forEach(function(val, key) {
if (signParams[val]) {
newArguments[val] = signParams[val];
}
});
const string = QueryString.stringify(newArguments) + '&key=' + key;
// 生成签名
return Crypto.createHash('md5')
.update(QueryString.unescape(string), 'utf8')
.digest('hex')
.toUpperCase();
},
// 根据对象生成xml
createXML: params => {
const builder = new XmlToJs.Builder();
return builder.buildObject(params);
},
// 解析xml
parserXML: xml => {
const Parser = new XmlToJs.Parser({ explicitArray: false, ignoreAttrs: false });
return new Promise((resolve, reject) => {
Parser.parseString(xml, function(err, result) {
if (err) reject(err);
resolve(result);
});
});
},
};
微信小程序获取返回的prepay_id,发起支付
// 发起支付
wx.requestPayment({
timeStamp: r.data.result.timeStamp,
nonceStr: r.data.result.nonceStr,
package: r.data.result.package,
signType: 'MD5',
paySign: r.data.result.paySign,
success(res) {
console.log('成功', res)
},
fail(res) {
}
})
手机扫一扫
移动阅读更方便
你可能感兴趣的文章