В этой статье в качестве примера используется uni-app, чтобы представить: вход в апплет WeChat, оплату (мини-программа, WeChat H5, не-WeChat H5), то есть метод шифрования запроса.
Вход в WeChat
WeChat меняет способ получения информации о пользователяхAPI
, поэтому не рекомендуется использовать кнопку@getuserinfo
метод, используяDOM
Щелчок, чтобы позвонитьgetUserProfile
API для получения информации о пользователе.
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;
},