Вход в апплет WeChat, оплата (мини-программа, WeChat H5, не-WeChat H5) — метод шифрования запроса.

Апплет WeChat

В этой статье в качестве примера используется uni-app, чтобы представить: вход в апплет WeChat, оплату (мини-программа, WeChat H5, не-WeChat H5), то есть метод шифрования запроса.

Вход в WeChat

WeChat меняет способ получения информации о пользователяхAPI, поэтому не рекомендуется использовать кнопку@getuserinfoметод, используяDOMЩелчок, чтобы позвонитьgetUserProfileAPI для получения информации о пользователе.

tips: расшифровать информацию userInfo CallgetUserProfileможет обновитьsession_key, так что новыйcodeРасшифровать не получится, нужно использовать предыдущийcode, здесь используется простой и грубый способ, который называется в хуке страницы showwx.login, Каждый раз, когда авторизация вызывается снова, чтобы обеспечить расшифровку информации о расшифровкеcodeТо же, что шифрование.

<template>
    <button @tap="getWxUserinfo">微 信 登 录</button>
</template>
export default {
    data() {
        return {
            wxCode: null
        }
    },
    onShow() {
        this.getCode()
    },
    methods: {
        // 获取 wxCode
        getCode(callback) {
            wx.login({
                success: res => {
                    this.wxCode = res.code
                    callback && callback(res.code)
                }
            });
        },
        // 获取用户信息
        getWxUserinfo() {
            wx.getUserProfile({
                desc: '用于完善用户资料',
                success: res => {
                    console.log(res)
                    wx.showLoading({
                            title: '正在登录',
                            mask: true
                    })
                    this.getCode(code => {
                        const data = {
                            code: this.wxCode,
                            iv: res.iv,
                            encryptedData: res.encryptedData
                        }
                        //发起请求登录
                        wx.request({
                            url: '/api/login',
                            method: 'POST',
                            success: res => {
                                console.log(res);
                                // 登录成功

                                wx.hideLoading()
                            }
                        })
                    })
                },
                fail: err => {
                    // 获取信息失败
                    console.log(err)
                }
            })
        }
    }
}

Платежный апплет WeChat

Стань первымcodeто есть использоватьuni.login()Затем вызовите фоновый интерфейсcodeИ номер заказа передается в фон, данные, возвращаемые фоном, являются параметром апплета для настройки платежа, а затем вызываютuni.requestPayment()просто хорошо

wx.login({
    success: res => {
        wx.request({
            url: '/api/wxpay',
            method: 'POST',
            data: {
                code: res.code,
                order_id: '订单id', // 后台接口参数 示例
                pay_type: 'wxpay',  // 后台接口参数 示例
            },
            success: res => {
                // 返回数据是json字符串,转为对象 - 具体根据后台返回数据操作
                const result = JSON.parse(res.data.pay_data)
                wx.requestPayment({
                    provider: 'wxpay',
                    timeStamp: result.timeStamp,
                    nonceStr: result.nonceStr,
                    package: result.package,
                    signType: result.signType,
                    paySign: result.paySign,
                    success: res => {
                        // 支付成功
                        console.log('success:' + JSON.stringify(res))
                    },
                    fail: err => {
                        // 支付失败
                        console.log('fail:' + JSON.stringify(err))
                    }
                })
            }
        })
    }
})

Оплата H5 (браузер WeChat/JSPAI)

получить код

Получите код при входе в систему, получите openId в фоновом режиме и сохраните его, а затем вам не нужно будет получать код, в котором openId используется в фоновом режиме (срок действия не истечет)

getCode(){
    let appid = 'xxxxxxxxxxxx'
    let url = 'https://xxx.xxxx.xxx'
    let redirect_uri = encodeURIComponent(url)//回调页面地址
    window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + redirect_uri + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"
}

Инкапсулировать платежный код H5

**
 * 支付
 * url 后台下单接口地址
 * data 下单参数
 * callback 回调函数
 */
const payH5 = {
    onBridgeReady: function(url, data, callback) {
        wx.request({
            url,
            method: 'POST',
            data,
            success(res) {
                // 后台返回的数据因为是字符串,转换对象
                const result_H5 = JSON.parse(res.data.pay_data)
                WeixinJSBridge.invoke(
                    'getBrandWCPayRequest', {
                        "appId": result_H5.appId, //公众号名称,由商户传入
                        "timeStamp": result_H5.timeStamp, //时间戳,自1970年以来的秒数
                        "nonceStr": result_H5.nonceStr, //随机串     
                        "package": result_H5.package,
                        "signType": result_H5.signType, //微信签名方式:     
                        "paySign": result_H5.paySign //微信签名 
                    },
                    function(res) {
                        if (res.err_msg == "get_brand_wcpay_request:ok") {
                            callback && callback('支付成功')
                        } else {
                            callback && callback('支付失败')
                        }
                    }
                );
            },
            fail(err) {
                console.log('网络错误:', err)
            }
        })
    },
    doPay(url, $params, callback) {
        if (typeof WeixinJSBridge == "undefined") {
            if (document.addEventListener) {
                document.addEventListener('WeixinJSBridgeReady', this.onBridgeReady, false);
            } else if (document.attachEvent) {
                document.attachEvent('WeixinJSBridgeReady', this.onBridgeReady);
                document.attachEvent('onWeixinJSBridgeReady', this.onBridgeReady);
            }
        } else {
            this.onBridgeReady(url, $params, callback)
        }
    }
}

export default payH5

оплатить звонок

Импортируйте этот файл на нужную страницу или смонтируйте его на прототипе vue (здесь представлено в uni-приложении)

// 引入: 
import H5Pay from './api/h5Pay.js' // H5Pay.doPay(url,params,callback)

export default {
    methods: {
        H5pay(){
            H5Pay.doPay(
            'url',
            {
                order_id: order_id,//订单号
                pay_type: '',//支付方式
            }, 
            function(msg) {
                // 支付结果
                console.log(msg)
            }
        )
    }
}

Оплата H5 (не встроенный браузер WeChat)

Условно говоря, интерфейс намного проще, и нет никаких хлопотных требований.url,window.location.href = mwev_url + redirect_uri(здесьredirect_uriЭто адрес перенаправленной страницы, а доменное имя должно совпадать с платным доменным именем! ! ! URL обязателенencodeURIComponentкодирование

dopayWeb() { //非微信浏览器支付
    wx.request({
        url: '/api/h5pay',
        method: 'POST',
        data: {
            order_id: '订单id', // 后台接口参数 示例
            pay_type: 'wxpay',  // 后台接口参数 示例
        },
        success(res) {
            console.log(res);
            const url = res.pay_url
            const redirect_uri = encodeURIComponent(url)
            window.location.href = url + "&redirect_uri=" + redirect_uri 
        },
        fail(err) {
            console.log('网络错误')
        }
    })
},

Различать встроенный ли браузер WeChat

function isMicroMessenger() {
    let userAgent = window.navigator.userAgent;    
    if(userAgent.indexOf('MicroMessenger') > -1) result = true;
    return false;
}

js генерирует шифрование подписи параметра запроса интерфейса

Определите правила:

Отсортируйте все параметры (в том числе публичные), инициирующие запрос, в порядке возрастания по ключу, а затем объедините их вkey1=value1&key2=value2форма

Такие как:parames = {b:value-b, c:value-c,a:value-a}После сортировки должно быть:string = "a=value-a&b=value-b&c=value-c"разберисьmd5: string = md5(string)Примечание: здесь нужно отфильтровать все пустые параметры, пустые параметры не передавать Сделайте это снова со строкой md5 и ключомmd5: sign = md5( string + secret ) ,sceretдля ключа серверная часть назначает

/** 
 * 定义对象排序方法
 */
objectSort(parames) 
{ 
    var newkeys = Object.keys(parames).sort();
    var newObj = {};
    for(var i = 0; i < newkeys.length; i++) 
    {
        newObj[newkeys[i]] = parames[newkeys[i]]; 
    }
    return newObj;
}
/** 
 * 计算签名方法
 */
makeSign(params)
{
    var sign = '';
    var parm = '';

    params = objectSort(params);
    for (let i in params)
    {
        var j = params[i];
        parm += i + '=' + j + '&';
    }
    parm = parm.slice(0,-1);
    parm.trim();

    sign = Md5.md5(Md5.md5(parm)+$secret);//$secret为密钥,后端分配 
    return sign;
},
/** 
 * 过滤data参数中的空字符
 */	
filterData(data){
    var result = {};
    for (let i in data) 
    {
        var value = data[i];
        if (typeof (value) == 'undefined') {
                value = '';
        }
        if(typeof(value) == 'string'){
                value = value.trim();
        }
        if(value)
        {
                result[i] = value;
        }
    }
    return result; 
},
/** 
 * 构建data参数
 */
bulidData(data) {
    if(typeof(data) != 'object'){
            data = {};
    }
    //构建参数
    data.timestamp = (new Date()).valueOf();
    data.app_id = Config.app_info.app_id;
    //过滤
    data = this.filterData(data);
    //检测用户是否登录
    var token = Helper.user.getToken();
    if(token)
    {
            data.token = token;
    }
    data.sign = this.makeSign(data);
    return data;
},