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;
}

结束:

如果只是单纯的支付,我们这里已经算是完成了.但是 支付成功之后验证是不可少的一步.之后会写到.

猜你喜欢

转载自blog.csdn.net/weixin_39907636/article/details/83412761