nodejs微信付出之扫码付出

媒介

本篇文章主假如纪录本人在微信扫码付出历程中所碰到的题目,给人人一个自创作用,愿望对你们有协助

开辟环境

  • nodejs v8.1.0
  • egg v1.1.0

准备工作

  • 微信民众号-appid
  • 微信商户号-mch_id
  • key值(署名算法所需,实在就是一个32位的暗码,可以用md5天生一个)(key设置途径:微信商户平台(pay.weixin.qq.com)–>账户设置–>API平安–>密钥设置)

扫码付出-一致下单

以下才用的是微信形式二,由于比较简朴

    let MD5 = require('md5'),
        xml2js = require('xml2js'),
        url = "https://api.mch.weixin.qq.com/pay/unifiedorder",// 下单要求地点
        appid = '民众号id',
        mch_id = '微信商户号';
        notify_url = '回调地点',
        out_trade_no = '本身设置的定单号',// 微信会有本身定单号、我们本身的体系须要设置本身的定单号
        total_fee = '定单金额',// 注重,单元为分
        body = '商品简朴形貌', 
        trade_type = 'NATIVE',// 交易类型,JSAPI--民众号付出、NATIVE--原生扫码付出、APP--app付出
        nonce_str = moment().format('YYYYMMDDHHmmssSSS'),// 随机字符串32位以下
        stringA = `appid=${民众号id}&body=${body}&mch_id=${微信商户号}&nonce_str=${nonce_str}&notify_url=${
        notify_url}&out_trade_no=${out_trade_no}&spbill_create_ip=${ctx.request.ip}&total_fee=${total_fee}&trade_type=${trade_type}`,
        stringSignTemp = stringA + "&key=xxxxxxxxxxxxxxxxx", //注:key为商户平台设置的密钥key
        sign = MD5(stringSignTemp).toUpperCase();  //注:MD5署名体式格局
    

以上就是我们所须要的一些参数
署名天生算法见微信官方
spbill_create_ip 是 终端ip地点

下面把一切的参数拼接成xml

    const formData = "<xml>";
        formData += "<appid>" + appid + "</appid>"; //appid
        formData += "<body>" + body + "</body>"; //商品或付出单扼要形貌
        formData += "<mch_id>" + mch_id + "</mch_id>"; //商户号
        formData += "<nonce_str>" + nonce_str + "</nonce_str>"; //随机字符串,不善于32位
        formData += "<notify_url>" + notify_url + "</notify_url>"; //付出胜利后微信服务器经由过程POST要求关照这个地点
        formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>"; //定单号
        formData += "<total_fee>" + total_fee + "</total_fee>"; //金额
        formData += "<spbill_create_ip>" + ctx.request.ip + "</spbill_create_ip>"; //ip
        formData += "<trade_type>NATIVE</trade_type>"; //NATIVE会返回code_url ,JSAPI不会返回
        formData += "<sign>" + sign + "</sign>";
        formData += "</xml>";
    // 这里运用了egg内里要求的体式格局
    const resultData = yield ctx.curl(url, {
            method: 'POST',
            content: formData,
            headers: {
                'content-type': 'text/html',
            },
        });

    // xml转json花样
    xml2js.parseString(resultData.data, function (err, json) {
        if (err) {
            new Error("剖析xml报错")
        } else {
            var result = formMessage(json.xml); // 转换成一般的json 数据
            console.log(result) //打印出返回的效果
        }
    })
    var formMessage = function (result) {
        var message = {};
        if (typeof result === 'object') {
            var keys = Object.keys(result);
            for (var i = 0; i < keys.length; i++) {
                var item = result[keys[i]];
                var key = keys[i];
                if (!(item instanceof Array) || item.length === 0) {
                    continue;
                }
                if (item.length === 1) {
                    var val = item[0];
                    if (typeof val === 'object') {
                        message[key] = formMessage(val);
                    } else {
                        message[key] = (val || '').trim();
                    }
                } else {
                    message[key] = [];
                    for (var j = 0, k = item.length; j < k; j++) {
                        message[key].push(formMessage(itemp[j]));
                    }
                }
            }
        }
        return message;
    }

上面运用了egg的要求体式格局,原生node可以运用request

    var request = require('request');
    request({
        url: url,
        method: "POST",
        body: formData
    }, function(error, response, body) {
        if (!error && response.statusCode == 200) {
        }
    }); 

假如要求胜利会终究返回一个xml,然后我们举行剖析成json的花样,内里会有一个code_urlout_trade_no,我们须要把这两个返回给前端,然后经由过程天生二维码展现给用户扫码,完成付出

监听付出是不是胜利

上面操纵完成以后,我们须要晓得用户是不是完成付出,由于用户会停留在该页面,我们须要在用户付完款以后,关照用户付出胜利。
起首,用户提议付出的时刻我们会天生二维码,让用户完成扫码付出,我们还要做的是,开一个定时器,每隔一段时间去发送一个要求,这个时刻,我们node背景就须要写一个查询定单的接口,之前我们拿到了out_trade_no,也就是我们体系内部的定单号,我们把这个数据发送给背景查询定单的接口,然后背景吸收到以后会要求微信的查询接口地点https://api.mch.weixin.qq.com/pay/orderquery,流程跟上面一样,只是接口地点和微信返回的xml不一样罢了,返回的字段会有一个状况即SUCCESSNOTPAY,我们可以经由过程推断是不是付出返回给前端,胜利以后提醒给用户付出胜利,封闭定时器。

回调地点

这个是非常主要的一环,大部分的操纵实在在上面就可以完成,然则有特别的状况,比方用户电脑断网发送不了要求,然则手机付款了,这就会致使我们纪录不到用户付出的信息。这个时刻回调地点就很主要了

设置回调地点

微信商户中间->产物中间->开辟设置->扫码付出

以后我们须要做的是后端用post来吸收微信发送的异步回调信息,也是xml的花样,这里注重,假如不支持吸收xml,可能会获得空的数据
这里还须要注重的是,我们在保留用户付出信息的同时,得先查改定单是不是付出,以避免反复操纵,可能会插进去多条纪录的状况

总结

微信扫码付出坑照样有的,假如你是第一次探索的话,下面排列一下须要注重的处所

  1. 署名算法要写准确,不然是不会胜利的,要拼接准确才行
  2. 微信返回的是xml花样的数据,我们得经由过程插件转成json,如许才轻易猎取数据
  3. 返回的code_url要给前端天生二维码用,然后须要开一个定时器查询该定单是不是完成付出,终究关照用户效果
  4. 回调地点很主要,我们后端须要post吸收微信返回的回调信息,然后保留信息,不过在保留用户付出信息的之前,我们得晓得该定单是不是已保留过,以避免反复增加。另有就是返回的是xml的数据,后端一定要保证可以吸收获得,根据一般的体式格局是吸收不了的,得分外设置。

文章地点 nodejs微信付出之扫码付出
个人博客地点 http://www.wclimb.site
GitHub地点 wclimb

    原文作者:wclimb
    原文地址: https://segmentfault.com/a/1190000013293668
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞