React Native (IOS和Android) 支付宝和微信支付集成实战(微信支付服务端篇)

序言React Native无论是在社区和应用程度上,在国内外是十分广泛和普及的。而支付宝和微信在支付模块上都有或多或少的支持,虽然没有完整的Demo,不过在我做过一个相关集成的项目后,在此我把相关的步骤和方法总结出来和大家分享,希望能够帮助大家少走弯路,快速集成。

微信支付——服务端集成

一、获取你的APPID,MCH_ID以及配置的密钥 key

微信没有沙箱,所以在商户平台上,创建你的应用后,请妥善保管这三个重要的配置内容。 和支付宝类似,需要在服务端进行生签操作,不同的是微信稍微步骤多一点,需要先获取prepay,并且访问和返回均为XML格式

 Android可按照官方文档 配置应用相关信息


二、配置和编写服务端代码

由于本分享以NodeJS为主,其他语言需要实现的步骤也是一样的,可参考官方文档 具体的操作详情以及需要注意的点如下:


1.按照微信统一下单的API,写好访问参数,并且进行生签,和支付宝一样,参数要按ASCII递增,生签后的签名值要全部转化为大写,获取prepay_id和相关内容。
2.注意所有进行签名的变量名均为小写,而签名的sign值最后要转化为大写
3.注意返回至客户端时,注意变量名的大小写,详情可参考react-native-wechat的github文档

// 配置相关变量
const APPID = ''          //你的微信应用APPID
const MCH_ID = ''         //你的商户ID
const KEY = ''            //设置的密钥key 
const NOTIFY_URL = 'http://192.168.1.45:3000/wechat/notify_url'     //设置你的回调地址
// 根据订单产生prepay的签名
var prepaySign = function (order) {
    var ret = {
        appid: APPID,
        body: order.body,
        mch_id: MCH_ID,
        nonce_str: order.nonce_str,
        notify_url: NOTIFY_URL,
        out_trade_no: order.out_trade_no,
        spbill_create_ip: order.spbill_create_ip,
        total_fee: order.total_fee,
        trade_type: 'APP'
    };
    var string = helper.raw(ret);
    string = string + '&key=' + KEY;
    var crypto = require('crypto');
    var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');
    return sign.toUpperCase();
}

//根据prepay的id,产生支付的签名
var paySign = function (prepay) {
    var ret = {
        appid: APPID,
        noncestr: prepay.nonce_str,
        package: 'Sign=WXPay',
        partnerid: MCH_ID,
        prepayid: prepay.prepayid,
        timestamp: prepay.timestamp
    };
    var string = helper.raw(ret);
    string = string + '&key=' + KEY;
    var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');
    return sign.toUpperCase();
}
// 访问微信,根据订单信息,获取prepay并且生成最后的支付订单内容
var requestPrepay = function (order) {

    return new Promise((resolve, reject) => {
        var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        var formData = "<xml>";
        formData += "<appid>" + APPID + "</appid>"; //appid  
        formData += "<body>" + order.body + "</body>";
        formData += "<mch_id>" + MCH_ID + "</mch_id>"; //商户号  
        formData += "<nonce_str>" + order.nonce_str + "</nonce_str>"; //随机字符串,不长于32位。  
        formData += "<notify_url>" + NOTIFY_URL + "</notify_url>";
        formData += "<out_trade_no>" + order.out_trade_no + "</out_trade_no>";
        formData += "<spbill_create_ip>" + order.spbill_create_ip + "</spbill_create_ip>";
        formData += "<total_fee>" + order.total_fee + "</total_fee>";
        formData += "<trade_type>APP</trade_type>";
        formData += "<sign>" + prepaySign(order) + "</sign>";
        formData += "</xml>";
        request({
            url: url,
            method: 'POST',
            body: formData
        }, function (err, response, body) {
            if (!err && response.statusCode == 200) {
                helper.getXMLNodeValue(body.toString("utf-8")).then((XML_RETURN) => {
                    var code = XML_RETURN.return_code[0];
                    var msg = XML_RETURN.return_msg[0];
                    if (code != 'SUCCESS' || msg != 'OK') {
                        deferred.reject({ message: XML_RETURN.return_msg[0] })
                        console.log(XML_RETURN)
                        return;
                    }

                    var prepay_id = XML_RETURN.prepay_id[0];

                    //签名  
                    var _paySign = paySign(Object.assign({ prepayid: prepay_id }, order));
                    var args = {
                        appId: APPID,
                        partnerId: MCH_ID,
                        prepayId: prepay_id,
                        nonceStr: order.nonce_str,
                        timeStamp: order.timestamp,
                        package: 'Sign=WXPay',
                        sign: _paySign
                    };
                    resolve(args);
                })

            } else {
                reject(err)
                console.log(body);
            }
        });
    })

}

//产生订单
wechat.post('/pay', function (req, res) {

    requestPrepay({
        body: '免费赠送IPhone X',
        out_trade_no: '453234533123',
        nonce_str: helper.createNonceStr(),
        spbill_create_ip: '192.168.1.45',  //一般可以从客户端获取用户IP,
        total_fee: '1',                    //单位为分
        timestamp: helper.createTimeStamp()
    }).then((data) => {
        res.send(data)
    })
})

//回调方法
wechat.post('/notify_url', function (req, res) {
    parser.parseString(req.body, function (err, result) {
        var wechatPayResult = result.xml

        console.log('wechat', wechatPayResult)
        var success = wechatPayResult.return_code[0] == 'SUCCESS'

        res.setHeader('content-type', 'application/xml')
        res.send('<xml><return_code><![CDATA[' + success ? 'SUCCESS' : 'FAIL' + ']]></return_code><return_msg><![CDATA[' + success ? 'OK' : 'FAIL' + ']]></return_msg></xml>')
    })

})


至此,微信服务端的配置已经完成了,相较于支付宝的服务端配置,稍微简单一点,因为不需要产生公钥私钥,但是总体步骤是差不多的。
在这里提醒开发者们,服务端生签是一个非常重要的部分,如果这块出现问题,客户端是无法正常运作的,所以请仔细认真的核对代码,避免出错,减少开发周期。
注意:以上代码请参考源码观看,有部分方法集成至其他文件。

鸣谢:我是一名来自盛安德的Shinetecher,感谢盛安德公司及同事们对IT技术的支持,分享和热情,让我有时间和动力完成此博文。

联系:欢迎各位朋友有任何问题和建议留言至此博客下,或者添加本人微信号:liyijia428 进行沟通交流学习

源码:https://github.com/likeconan/Alipay_Wechat_Integration


猜你喜欢

转载自blog.csdn.net/likeconan123/article/details/79006857
今日推荐