// Order.js 架构
const mongoose = require('mongoose');
const Order = new mongoose.Schema({
openid: { // 用户唯一标识
type: String
},
prepay_id: { // 预支付会话标识
type: String
},
out_trade_no: { // 商户订单号
type: String
},
transaction_id: { // 微信订单号
type: String
},
status: { // 订单状态
type: Number
},
goods: [{ // 商品信息
good_id: {
type: Number
},
title: {
type: String
},
num: {
type: Number
},
price: {
type: Number
},
img: {
type: String
}
}],
create_time: { // 订单创建时间
type: String
},
pay_time: { // 订单支付时间
type: String
}
});
module.exports = mongoose.model('Order', Order);
yarn add md5
const md5 = require('md5')
data: {
appid: 'wx080a191278b69c58',
body: '纵翔商城-购物结算',
mch_id: '1560000000',
nonce_str: Math.random().toString(36).slice(-8),
notify_url: 'https://api.domain.com:3000/pay/callback',
openid: this.getOpenIdByLocal(),
out_trade_no: 'wx_' + nonce_str + '_' + String(Math.round(new Date())),
spbill_create_ip: '47.102.154.110',
total_fee: 0,
trade_type: 'JSAPI'
}
<view class="tui-pr25">
<tui-button type="danger" shape="circle" @click="btnPay">确认支付</tui-button>
</view>
/*
* 封装参与签名算法参数ASCII码排序
* https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3
*/
const utils = {
payParamsSort(str) {
var strArr = str.split('.');
var newStr = Array.prototype.sort.call(strArr, function(a, b) {
for (var i = 0; i < a.length; i++) {
if (a.charCodeAt(i) == b.charCodeAt(i)) continue;
return a.charCodeAt(i) - b.charCodeAt(i);
}
});
return newStr;
}
}
module.exports = {
payParamsSort: utils.payParamsSort
}
// 获取当前用户openid
getOpenIdByLocal() {
return uni.getStorageSync('uid');
}
// 将订单提交到商户后台
generateOrders(order) {
uni.request({
url: this.baseUrl + '/pay/order', //仅为示例,并非真实接口地址。
method: 'POST',
data: {
order: order
},
success: (res) => {
if(res.status === 200 && res.data.msg == 'ok') {
console.log('generate order success');
}
}
});
}
// 支付
btnPay() {
let keyStr = Object.keys(this.obj);
let a = '';
keyStr.forEach((k) => {
a += (k + '.')
})
let sort = payParamsSort(a.substring(0, a.length - 1));
let o = {};
sort.forEach((s) => {
o[s] = this.obj[s];
})
let stringA = '';
Object.keys(o).forEach((key) => {
stringA += key + '=' + o[key] + '&';
});
console.log(stringA.substring(0, stringA.length - 1));
const key = this.key;
const stringSignTemp = stringA.substring(0, stringA.length - 1) + "&key=" + key;
const sign = md5(stringSignTemp).toUpperCase();
this.obj.sign = sign;
// 统一下单(预支付)
uni.request({
method: 'POST',
url: this.baseUrl + '/pay/unifiedorder',
data: this.obj,
header: {
'Content-Type': 'application/json'
},
success: (res) => {
console.log(res);
// 生成商户订单
const order = {};
order.openid = this.getOpenIdByLocal();
order.prepay_id = res.data.result.xml.prepay_id;
order.out_trade_no = this.obj.out_trade_no;
order.transaction_id = '';
order.status = 1;
order.goods = [];
order.create_time = String(Math.round(new Date() / 1000));
order.pay_time = '';
this.generateOrders(order);
// 申请支付
const payObj = {
appId: 'wx080a191278b69c58',
timeStamp: String(Math.round(new Date() / 1000)),
nonceStr: 'zephyr',
package: 'prepay_id=' + res.data.result.xml.prepay_id,
signType: 'MD5',
};
let keyStr2 = Object.keys(payObj);
let a = '';
keyStr2.forEach((k) => {
a += (k + '.')
})
let sort = payParamsSort(a.substring(0, a.length - 1));
let o = {};
sort.forEach((s) => {
o[s] = payObj[s];
})
let stringA = '';
Object.keys(o).forEach((key) => {
stringA += key + '=' + o[key] + '&';
});
const key = this.key;
const stringSignTemp = stringA.substring(0, stringA.length - 1) + "&key=" + key; //注:key为商户平台设置的密钥key
const sign = md5(stringSignTemp).toUpperCase();
// 小程序调起支付API
wx.requestPayment({
'timeStamp': payObj.timeStamp,
'nonceStr': payObj.nonceStr,
'package': payObj.package,
'signType': payObj.signType,
'paySign': sign,
'success':function (res) {
console.log(res);
},
'fail':function (res) {
console.log(res);
},
'complete':function (res) {
console.log(res);
}
})
},
fail: (err) => {
console.log(err);
}
});
}
// 新增order
async addOrder(ctx, next) {
const orderItem = new Order(ctx.request.body.order);
try {
const res = await orderItem.save();
ctx.body = {
code: 1,
msg: 'ok',
result: res
}
} catch (err) {
console.log(err);
ctx.body = {
code: 0,
msg: err.message || '服务器错误'
}
}
}
订单通知、查询订单、退款等功能开发中...
DONE !