nodejs+Koa2实现小程序的微信支付请求(一)

nodejs+koa2 实现微信支付请求

在开发之前我们先看一下小程序向微信请求支付的业务流程

 第一步,小程序先发起支付请求

小程序首先先向“商家系统后台”发起请求支付,也就是我们自己的后端服务,生成平台订单和签x

第二步,我们的nodejs服务接收到请求之后,处理支付请求,签名后强微信请求支付

let xmlData = await WXPlay.requestWXPay(wxPayInfo);  ->这里是向微信支付服务器请求支付的地方

router.post('/xxxxPay',async (ctx) => {
    const v = await new PayFeeValidator().validate(ctx);
    let body = ctx.request.body;
    let payAmount = Math.floor(parseFloat(body.payAmount))*100);
    let orderType = body.orderType;
    let content = body.content)?body.content):'支付费用';
    let wxPayInfo = {
        userId: ctx.auth.uid,
        entriesId: body.entriesId,
        openId: header.openid,
        payAmount: payAmount,
        money: body.payAmount,
        ip: host,
        productIntro: content,
        orderType: orderType
    }
    let xmlData = await WXPlay.requestWXPay(wxPayInfo);
    let response = xmlData.xml

    if (response.return_code === 'SUCCESS') {
        if (response.result_code === 'SUCCESS') {
            let timeStamp = createTimeStamp();
            let nonceStr = response.nonce_str;
            let prepay_id = response.prepay_id;
            let appid = global.config.violinWx.appid;
            let package = 'prepay_id=' + prepay_id;
            let apiKey = global.config.violinWx.payApiKey;
            let paySign = getPaySignJs(appid, timeStamp, nonceStr, package, apiKey);
            const order = await Order.getOrderDetailByPer(prepay_id);
            ctx.body = {
                code: 0,
                msg: 'SUCCESS',
                data: {
                    timeStamp: timeStamp,
                    nonceStr: nonceStr,
                    package: package,
                    paySign: paySign,
                    orderNo: order.orderNo
                }
            }
        } else {
            ctx.body = {
                code: response.err_code,
                msg: response.err_code_des
            } 
        } 
    } else {
        ctx.body = {
            code: 1,
            msg: response.return_msg
        }
    }
})

我们的服务端拿到微信的支付响应之后,返回给小程序以下参数

timeStamp: 时间戳

nonceStr: 随机字符串

package: 订单详情扩展字符串

paySign: 签名

orderNo: 我们系统的订单号

 signType: 签名方式

小程序拿到这些信心后才开始真正调起支付,代码如下

                wx.requestPayment({
                    timeStamp: res.data.timeStamp.toString(),
                    nonceStr: res.data.nonceStr,
                    package: res.data.package,
                    signType: 'MD5',
                    paySign: res.data.paySign,
                    success (result) {
                        wx.showToast({
                            title: `支付成功`,
                            icon: 'none',
                            duration: 2000
                        })
                        // 下面做支付成功的事情
                    },
                    fail (result) {
                        wx.showToast({
                            title: `您的支付请求失败,请重新支付`,
                            icon: 'none',
                            duration: 2000
                        })
                        
                    }
                })

微信支付成功后下面需要处理的就是微信收到付款后的回调,这里的支付回调接口一定要在微信支付平台配置正确

router.post('/XXXPayNotice', async (ctx) => {
    let result = 1;
    const wxResponse = ctx.body.xml;
    if (wxResponse && wxResponse.return_code[0] === 'SUCCESS') {
        if (wxResponse.result_code[0] === 'SUCCESS') {
            let timeEnd = wxResponse.time_end[0];
            let pattern = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
            let formateDate = timeEnd.replace(pattern, '$1/$2/$3 $4:$5:$6');
            let order = {
                orderStatus: 1,
                confirmTime: new Date(),
                arrivalTime: formateDate,
                confirmFlag: 1,
                transactionNo: wxResponse.transaction_id[0],
                orderNo: wxResponse.out_trade_no[0]
            }
            const orderR = await Order.getOrderByOrderNo(order.orderNo);
            if (orderR) {
                let payAmount = Math.floor(parseFloat(orderR.payAmount)*100); 
                if (payAmount === parseInt(wxResponse.total_fee[0])) {
                    await Order.updateOrderByWxResponse(order);
                    result = 1;
                } else {
                    result = 2;
                }
                if (orderR.orderType === 0) {
                    let entries = {
                        entriesStage: 2,
                        payStatus: 1,
                        orderNo: order.orderNo,
                        entriesId: orderR.entriesId
                    }
                    if( result === 1) {
                        await V_Entries.updateEntriesPayInfo(entries);
                        // 修改用户标记为已支付用户
                        await V_User.updateIsEnteriesUser(1,orderR.userId);
                    }
                }
                if (orderR.orderType === 1) {
                    // 处理大师班报名
                    let payInfo = {
                        payStatus: 1,
                        orderNo: order.orderNo
                    }
                    await T_Student_Class.updatePayInfoByOrderNo(payInfo);
                }
            } else {
                result = 3;
            }
        } else {
            let timeEnd = wxResponse.time_end[0];
            let pattern = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
            let formateDate = timeEnd.replace(pattern, '$1/$2/$3 $4:$5:$6');
            let order = {
                orderStatus: 2,
                confirmTime: new Date(),
                arrivalTime: formateDate,
                confirmFlag: 1,
                transactionNo: wxResponse.transaction_id[0],
                orderNo: wxResponse.out_trade_no[0]
            }
            await Order.updateOrderByWxResponse(order)
        }
    }
    if (result === 2) {
        ctx.type = 'application/xml';
        ctx.headers[{
            'Content-Type': 'text/xml'
        }];
        ctx.body = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[未找到订单]]></return_msg></xml>';
    } else if (result === 3) {
        ctx.type = 'application/xml';
        ctx.headers[{
            'Content-Type': 'text/xml'
        }];
        ctx.body = '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[金额校验失败]]></return_msg></xml>';
    } else {
        ctx.type = 'application/xml';
        ctx.headers[{
            'Content-Type': 'text/xml'
        }];
        ctx.body = '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
    }    
})

微信支付成功的通知参数消息体

let wxResponse = {

    "appid": ["XXXXX"],

    "attach": ["XXXX"],

    "bank_type": ["OTHERS"],

    "cash_fee": ["1"],

    "fee_type": ["CNY"],

    "is_subscribe": ["N"],

    "mch_id": ["XXXX"],商户号

    "nonce_str": ["uNE3NFA0nGPAU7iiOGsuDRkC6qNcNQc8"],

    "openid": [""], 支付用户的openID

    "out_trade_no": [""],

    "result_code": ["SUCCESS"],

    "return_code": ["SUCCESS"],

    "sign": ["C82D1DE210366E280DBBE6F7D9A3A63A"],

    "time_end": ["20200628212320"],

    "total_fee": ["1"],

    "trade_type": ["JSAPI"],

    "transaction_id": [""]

}

 */

里面用的签名和具体的支付请求,查看这里签名预支付请求

参数说明,参考微信支付-开发者文档

 

未完待续

实现代码:nodejs+koa2实现微信小程序签名和请求支付(二)_仗剑走天涯的博客-CSDN博客废话不多说直接上代码:const getTradeNo = function() { let date = new Date(); let arr = [ date.getFullYear(), ((date.getMonth() + 1)>=10?(date.getMonth() + 1):'0'+(date.getMonth() + 1)), date.getDate(), date.getHours(), https://blog.csdn.net/u012885136/article/details/121359473 

欢迎交流,分享不易,谢谢点赞!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪山上的小灰熊

谢谢支持哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值