1. 程式人生 > >node 微信小程式支付

node 微信小程式支付

Node 微信支付

說明

因為最近第一次完成微信支付和提現,遇到了很多問題,自己記性又差所以記錄一下.該篇只是node後端流程,申請支付功能或是前端程式碼沒有且為小程式支付:
第一次寫一定不會很好,如果遇到問題 可以加我qq 798474927

業務流程

Alt

簽名

簽名應該是最核心的一步,並且只有這一步哈哈哈~~~~~~~所以我們要寫一個簽名的介面:

//支付訂單
exports.miniPay = function(req,res) {
let payData = req.body; let openId = payData.openId; //trade_type=JSAPI,此引數必傳,使用者在商戶appid下的唯一標識。 let appid = payData.appid; //微信分配的小程式ID let attach = payData.attach; //附加資料,在查詢API和支付通知中原樣返回,可作為自定義引數使用。 let mch_id = payData.mch_id; //微信支付分配的商戶號 let nonce_str = Math.random
().toString(36).substr(2, 15); //隨機字串,長度要求在32位以內。 let body = payData.body; //商品描述 let out_trade_no = payData.orderNumber; //商戶系統內部訂單號,要求32個字元內,只能是數字、大小寫字母_-|*@ ,且在同一個商戶號下唯一 let total_fee = payData.total_fee; //金額 分為單位 let spbill_create_ip =
"123.12.12.123"; //亂寫的 let notify_url = "http://192.168.1.141"; //亂寫的 let trade_type = "JSAPI"; //小程式為JSAPI let timeStamp = wxPay.time(); //時間戳 /*該方法為第一次簽名方法,微信簽名共有兩次 後面我會將該方法貼出來wxPay.paysignMini 這個是第一次簽名,簽名規則按照文件 */ let sign = wxPay.paysignMini(appid,mch_id,body,nonce_str,openId,trade_type,notify_url,spbill_create_ip,out_trade_no,total_fee,attach); let formData = "<xml>"; formData += "<appid>"+appid+"</appid>"; formData += "<attach>"+attach+"</attach>"; formData += "<body>"+body+"</body>"; formData += "<mch_id>"+mch_id+"</mch_id>"; formData += "<nonce_str>"+nonce_str+"</nonce_str>"; formData += "<notify_url>"+notify_url+"</notify_url>"; formData += "<openid>"+openId+"</openid>"; formData += "<out_trade_no>"+out_trade_no+"</out_trade_no>"; formData += "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"; formData += "<total_fee>"+total_fee+"</total_fee>"; formData += "<trade_type>"+trade_type+"</trade_type>"; formData += "<sign>"+sign+"</sign>"; formData += "</xml>"; /*簽名成功之後,變成xml格式的資料,向微信伺服器傳送https請求,若成功,微信伺服器會返回xml格式資料 解析之後會得到預付交易回話表示prepay_id 在下嗎的方法中用到了兩個封裝的方法,之後會貼出來wxPay.getXMLNodeValue(因為微信返回的是xml形式的所以要寫一個解析的方法),wxPay.paysignMini2(第二次簽名的方法,然後後端就應該沒啥事了) */ //!!!!!!!!!!!!!這裡要注意package這個引數 一定要prepay_id=字串與prepay_id進行拼接 request({ url: "https://api.mch.weixin.qq.com/pay/unifiedorder", method: 'POST', body: formData }, function (err, response, body) { if (!err && response.statusCode == 200) { let msg = wxPay.getXMLNodeValue('return_msg', body.toString('utf-8')); // 這個引數可選,微信給咱們正確或錯誤資訊 let prepay_id = wxPay.getXMLNodeValue('prepay_id', body.toString('utf-8')); let nonce_str = wxPay.getXMLNodeValue('nonce_str', body.toString('utf-8')); let package = 'prepay_id='+prepay_id; timeStamp = timeStamp.toString(); let paySign= wxPay.paysignMini2(appid,nonce_str,package,timeStamp); let data = { msg :msg, nonce_str:nonce_str, prepay_id:prepay_id, timeStamp:timeStamp, paySign:paySign }; res.json(data) }}); }; //好啦 咱們就沒啥事了

輔助方法

之前我們好像就提到了三個方法 在這裡寫一下
wxPay.paysignMini() ,wxPay.getXMLNodeValue() wxPay.paysignMini2()
簽名介面教研工具
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
如果是簽名錯誤,一定要仔細看看自己引數,平常心 ~~~~

//
exports.paysignMini = (appid,mch_id,body,nonce_str,openId,trade_type,notify_url,spbill_create_ip,out_trade_no,total_fee,attach)=> {
    let rets = {
        appid: appid,
        body: body,
        mch_id: mch_id,
        nonce_str:nonce_str,
        openid:openId,
        trade_type:trade_type,
        notify_url:notify_url,
        spbill_create_ip:spbill_create_ip,
        out_trade_no:out_trade_no,
        total_fee:total_fee,
        attach:attach
    };
    key = "********************";			//金鑰
    var str = raw(rets);
    //將引數拼接成字串
    str = str + '&key='+key;
    var md5Str = crypto.createHash('md5').update(str).digest('hex');
    md5Str = md5Str.toUpperCase();
    return md5Str;
};
//二次簽名sign
exports.paysignMini2 =(appid,nonceStr,package,timeStamp)=> {
    let reta = {
        appId: appid,
        nonceStr: nonceStr,
        package:package,
        signType: 'MD5',
        timeStamp:timeStamp.toString()
    };
    key = "**********************";		//金鑰
    var str = raw1(reta);
    //將引數拼接成字串
    str = str + '&key='+key;
    console.log("MD5Str:",str);
    var md5Str = crypto.createHash('md5').update(str).digest('hex');
    md5Str = md5Str.toUpperCase();
    return md5Str;
};

exports.getXMLNodeValue = (node_name,xml)=>{
        let tmp = xml.split("<"+node_name+">");
        if(tmp[1]!=undefined){
            let _tmp = tmp[1].split("</"+node_name+">");
            let tmp1 = _tmp[0].split('[');

            let _tmp1 = tmp1[2].split(']');
            return _tmp1[0];
        }
};



function raw(args) {
    var keys = Object.keys(args);
    keys = keys.sort();
    var newArgs = {};
    keys.forEach(function (key) {
        // newArgs[key.toLowerCase()] = args[key];
        newArgs[key] = args[key]; });
    var str = '';
    for (var k in newArgs) {
        str += '&' + k + '=' + newArgs[k];
    }
    str = str.substr(1);
    console.log(str)
    return str;
}

結束:

如果只是單純的支付,我們這裡已經算是完成了.但是 支付成功之後驗證是不可少的一步.之後會寫到.