本文档 当中所用到的: const $request = this.request const post = $request.call('passport/wxLogin',data) post.then(res=>{}).catch() 是自己封装的请求方法,如axios,参考时可自行更改 复制代码
1、js生成接口请求参数签名加密
定义规则:
对所有发起请求的参数(包括公共参数),按key进行升序排序 ,然后组合成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; }, 复制代码
微信登录
这里采用 button的开放属性 open-type 触发@getuserinfo事件 获取到code 发送给后台 换取token 存到storge;详细参考微信官方文档
<template> <button openType="getUserInfo" lang="zh_CN" @getuserinfo="getUserInfo">授权登录</button> </template> methods: { getCode(callback) { wx.login({ success: res => { console.log(res); if (res.errMsg == 'login:ok') { if (callback) { callback(res.code) } this.code = res.code } } }); }, getUserInfo(e) { this.getCode(code => { if (e.detail.errMsg !== 'getPhoneNumber:ok') { return false; } wx.showLoading({ title: '正在登录', mask: true }); const data = { code:this.code, iv:e.detail.iv, encryptedData:e.detail.encryptedData } //发起请求登录 const $request = this.request const post = $request.call('passport/wxLogin',data) post.then(res =>{ console.log(res) uni.setStorageSync('_user_login_token', res.data.token) }).catch(err => { //常规catch, 一般不用修改 $request.callError(err) }) }); } } 复制代码
微信小程序支付
首先获取code{uni.login()} 然后调后台接口 把code和订单好传给后台,后台 返回的数据就是小程序调支付的参数
{uni.requestPayment()} 就这么简单
const $request = this.request const resLogin = await uni.login() if (resLogin[0] !== null || resLogin[1].errMsg !== 'login:ok') { return uni.showToast({ title: 'code获取失败', icon: 'none' }) } const code = resLogin[1].code const post = $request.call('order/doPay', { order_id: this.order_id, pay_type: '无忌微信小程序支付', code: code }) post.then(data => { // 返回数据,只返回接口中的data const result = JSON.parse(data.data.pay_data)//字符串转对象 uni.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)) this.requestDetail() }, fail: err => { console.log('fail:' + JSON.stringify(err)) } }) }).catch(function(e) { //常规catch, 一般不用修改 $request.callError(e) 复制代码
4、H5支付(微信内浏览器/JSPAI)
获取code
在登录时就获取code,后台得到openId将其存起来,之后后台在用到openId的地方就不用再获取了(不会过期)
getCode(){ let appid = {appid} 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支付代码
** * 支付 * 这里的 $request.call()为自己封装的请求方法,使用时请自行更改 */ var payH5 = { onBridgeReady: function(url, $params,success) { const post_H5 = $request.call(url, $params) post_H5.then(data => { // 返回数据,只返回接口中的data const result_H5 = JSON.parse(data.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") { var msg = '支付成功'; success(msg) } else { var msg = '支付失败'; success(msg) } }); }).catch(function(e) { //常规catch, 一般不用修改 $request.callError(e) }) }, doPay(url, $params,success) { 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,success) } } } export default payH5 复制代码
支付调用
将这个文件引入需要的页面或者挂载到vue原型上(这里以uni-app中介绍)
在main.js中 引入: import H5Pay from './api/h5Pay.js' Vue.prototype.H5Pay = H5Pay 页面引用: this.H5Pay.doPay(url,params,callback) 参数: url:接口请求地址 params:请求参数 callback:回调方法(回调支付结果) H5pay(){ this.H5Pay.doPay('order/doPay', { order_id: order_id,//订单号 pay_type: '',//支付方式 }, function(msg) { uni.showToast({ title: msg, icon:'none' }) uni.navigateBack() }) } 复制代码
5、H5支付(非微信内置浏览器)
相对来说前端简单很多,没什么麻烦要求 后台会返回一个mwev_url ,window.location.href = mwev_url + redirect_uri (这里的redirect_uri 是重定向的页面地址,域名要和支付域名一致 !!!做编译encodeURIComponent(url))
dopayWeb() { //非微信浏览器支付 const $request = this.request; const post = $request.call('order/doPay', { order_id: this.order_id,//订单号 pay_type: 'nweb'//支付方式 }); post.then(res => { console.log(res); let url = res.mwev_url let redirect_uri = encodeURIComponent(url) window.location.href = url + "&redirect_uri=" + redirect_uri }).catch(function(e) { $request.callError(e) }); }, 复制代码
6、 区分是否是微信内置浏览器
function isMicroMessenger() { let result = false; let userAgent = window.navigator.userAgent; if(userAgent.indexOf('MicroMessenger') > -1) { result = true; } return result; } 复制代码
原文地址:http://www.wxapp-union.com/portal.php?mod=view&aid=5615
作者:兮丶