/**
* @function silentLogin 小程序静默登录
* @param cb 回调函数
* @param extraParams 额外的私有参数, 如果静默授权的时候有一些参数是需要自己传递的,可以定义在这里,在回调函数里面可以直接进行 比如:silentLogin(cb,{sex:'man'}) 那么在 cb(data) 的回参里面就可以直接通过 data.extraParams 获取到 sex 的对象 详情可以参考 demo
* @description 根据方法的原子性,一个方法设计只应该处理当前业务,但是考虑到当前小程序的实际业务,这里不做功能和业务的区分 该项目目的就是根据授权获取用户信息
* 后面如果需要改动,只需要将方法中的回调函数去除,将方法本身返回值 return 即可
*/
export const silentLogin = (cb, extraParams = {}) => {
console.log('🚀 静默授权扩展参数:', extraParams)
if (cb) {
uni.login({
success: (res) => {
if (res.code) {
// TODO: 获取到 code 进行获取 openID
getOpenId(res.code, cb, extraParams)
} else {
uni.$u.toast('登录失败!' + res.errMsg)
}
}
})
} else {
uni.$u.toast('缺少回调函数')
}
}
// TODO: 获取 openID
export const getOpenId = (code = '', cb, extraParams) => {
if (code) {
// TODO: 请求获取 openId 的接口 -> 根据 openId 获取用户信息
wxAppletAuthorize({ code: code }).then((openId) => {
const userLoginInfos = { code, openId } //TODO: 用户的登录信息
uni.setStorageSync('userLoginInfos', userLoginInfos) // TODO: 存储用户的登录信息
getUserInfos(code, openId, cb, extraParams)
})
}
}
// TODO: 根据 openId 获取用户信息 getUserInfos
export const getUserInfos = (code = '', openId = '', cb, extraParams) => {
if (openId) {
// TODO: 获取用户信息 -> 存储用户信息
let resultInfos = {}
wxAppletGetAppUser({ openId })
.then((res) => {
resultInfos = res
})
.catch((err) => {
console.error(err)
})
const userInfos = {
...resultInfos,
extraParams,
code,
openId
}
console.log('🚀 授权获取到的用户信息', userInfos)
cb(JSON.stringify(userInfos))
}
}
/**
* @function appletPay 微信小程序支付
* @param data 支付入参 [参数说明:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=5]
* @param successCb 支付成功回调函数
* @param failCb 支付失败回调函数
*/
export const appletPay = (data, successCb, failCb) => {
const { timeStamp, nonceStr, signType, paySign } = data
uni.requestPayment({
timeStamp,
nonceStr,
signType,
paySign,
package: data.package,
success(res) {
// TODO: requestPayment:ok 调用支付成功
console.log('支付成功回参:', res)
uni.$u.toast('支付成功')
if (res.errMsg === 'requestPayment:ok') {
successCb(data)
}
},
fail(errMsg) {
console.log('支付失败回参:', errMsg)
// TODO: requestPayment:fail (detail message) 调用支付失败,其中 detail message 为后台返回的详细失败原因
// TODO: requestPayment:fail cancel 用户取消支付
if (errMsg === 'requestPayment:fail cancel') {
uni.$u.toast('取消支付')
} else {
uni.$u.toast('支付失败')
}
failCb(data)
},
complete: function (com) {
console.log('执行结束:', com)
}
})
}
/**
* @function contractSigning 小程序纯签约
* @param data 签约入参 [参数说明:https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_3.shtml]
* @param successCb 支付成功回调函数
* @param failCb 支付失败回调函数
*/
export const contractSigning = (data, successCb, failCb) => {
const { appId, path, extraData } = data
wx.navigateToMiniProgram({
appId,
path,
extraData,
success(res) {
// TODO: 成功跳转到签约小程序
console.log('签约成功回参:', res)
successCb(res)
},
fail(errMsg) {
// TODO: 未成功跳转到签约小程序
console.log('签约失败回参:', errMsg)
failCb(errMsg)
},
complete: function (com) {
console.log('执行结束:', com)
}
})
}
// TODO: 设置更新埋点参数
let tempObj = []
export const setAndUpdateBuriedParams = (BuriedParams = {}) => {
tempObj.push(BuriedParams)
uni.setStorageSync('productBaseInfos', { ...Object.assign({}, ...tempObj) }) // TODO: 更新缓存
console.log('🚀 埋点的扩展参数:', uni.getStorageSync('productBaseInfos'))
}
/**
* @function choseArrayByParams 选择数组中的某一个元素 根据 key 和 value 筛选数组中对应的对象
* @param sourceArr 数据源 数组
* @param key 对象的 key
* @param val 对象的 val
*/
export const choseArrayByParams = (sourceArr, key, val) => {
if (sourceArr) {
const result = sourceArr.find((data) => {
return data[key] === val
})
return result
} else {
console.error(sourceArr, '不是一个数组')
}
}
// TODO: 获取 URL 中参数的 value 只支持一次 encode 或者 没有 encode 的 url 两次或以上的请自行 decode 之后进行使用该方法
export const getParamByUrl = (url) => {
const res = {}
if (url.includes('?')) {
const str = url.split('?')[1]
const arr = str.split('&')
arr.forEach((item) => {
const key = item.split('=')[0]
const val = item.split('=')[1]
res[key] = decodeURIComponent(val) // 解码
})
}
return res
}
// TODO: 设置分享参数 updateShareObject 最新的分享参数
export const setShareParams = (type = '', updateShareObject = {}) => {
const { title = '台风暴雨损失大,家财保障千万家', image: imageUrl = `${FILE_URl}/weixinsvr/front/2023/8/21/share.png`, path = '/pages/tabPages/insure/index' } = updateShareObject
if (type === 'timeline') {
return { title, imageUrl, query: path }
}
return { title, imageUrl, path }
}
/**
* @Description: 封装支付和签约的接口请求以及执行微信执行方法
* @author:clearlove
* @param
* @return
* @createTime: 2023-08-19 15:04:18
*/
import { getPayUrl, insurancePay } from '@/apis/transaction.js'
import { contractSigning, appletPay, getParamByUrl, silentLogin } from '@/utils/tools.js'
let callBackParams = {} // TODO: 支付回调参数
let payType = 1 // TODO: 记录支付方式 没有授权的时候重新支付使用
// TODO: 获取支付链接
export const getPayUrlByNextStepParams = (data = {}, paymentMethod = 1) => {
payType = paymentMethod // TODO: 记录支付方式
const { openId } = uni.getStorageSync('userLoginInfos') // TODO: 判断用户是否登录过
if (openId) {
getPayUrl(data).then((res) => {
console.log('🚀 获取到的支付链接:getPayUrlByNextStepParams', res)
if (res) {
const getOrderBaseInfos = { orderName: data['tenantOrderInsuredList'][0]['tenantOrderProductList'][0]['productName'] } // TODO: 获取订单产品名称
const setOrderParams = { ...getParamByUrl(res.paymentUrl), ...getOrderBaseInfos } // TODO: 设置统一下单的参数
unifiedOrderPlacement(setOrderParams, paymentMethod)
}
})
} else {
silentLogin(updateUserLoginInfos, data) // TODO: 进行授权登录 登录之后进行重新支付
}
}
// TODO: 统一下单
export const unifiedOrderPlacement = (data, paymentMethod) => {
console.log('🚀 统一下单参数:unifiedOrderPlacement', data)
console.log('🚀 用户登录信息', uni.getStorageSync('userLoginInfos'))
const { openId: openid } = uni.getStorageSync('userLoginInfos')
const { businessTradeNo, orderNo, tenantId, orderName } = data
const setPayParams = {
businessTradeNo,
orderNo,
orderName,
payWay: paymentMethod === 1 ? 'wxAppletspay' : 'wxAppletsSign', // TODO: wxAppletspay 支付 wxAppletsSign 签约
srcType: 'JS',
tenantId,
openid
}
callBackParams = { orderNo, tenantId, businessTradeNo }
// TODO: 下单成功 直接拉起微信支付/拉起签约 即可
insurancePay(setPayParams).then((payData) => {
console.log('🚀 微信支付参数:', payData)
if (payData) {
if (paymentMethod === 1) {
appletPay(setWechatPayParams(payData), resultCb, resultCb) // TODO: 设置拉起微信支付的参数 / 执行支付
} else {
contractSigning(setWechatcontractParams(getParamByUrl(payData.redirect_url)), resultCb, resultCb) // TODO: 设置拉起微信纯签约的参数 / 执行纯签约
}
}
})
}
// TODO:设置拉起微信支付的参数
const setWechatPayParams = (params) => {
const { timeStamp, nonceStr, sign_type: signType, prepayId, sign: paySign } = params
const setParams = { timeStamp, nonceStr, package: prepayId, signType, paySign }
return setParams
}
// TODO: 设置拉起微信纯签约的参数
const setWechatcontractParams = (params) => {
const signParams = params
const { appid, contract_code, contract_display_account, mch_id, notify_url, outerid, plan_id, request_serial, return_web, sign, timestamp, version } = signParams
const appletContractParams = {
appId: 'wxbd687630cd02ce1d',
path: 'pages/index/index',
extraData: {
appid,
contract_code,
contract_display_account,
mch_id,
notify_url,
plan_id,
request_serial,
timestamp,
sign
}
}
return appletContractParams
}
// TODO: 结果页回调函数
const resultCb = () => {
// FIXME: 这里因为后端接口的 orderNo 和 businessTradeNo 反复不定 导致不同接口请求的参数不一致 只能全部获取出来进行分别赋值
const { orderNo, tenantId, businessTradeNo } = callBackParams
if (payType === 1) {
uni.navigateTo({
url: `/pages/tabPages/results/index${uni.$u.queryParams({ orderNo: businessTradeNo, tenantId })}`
})
} else {
uni.navigateTo({
url: `/pages/tabPages/transfer/index${uni.$u.queryParams({ orderNo, tenantId, businessTradeNo })}`
})
}
}
// TODO: 更新用户信息 callBackPayParams就是上面的调用静默授权接口的第二个参数 data
const updateUserLoginInfos = (callBackPayParams) => {
console.log('更新用户信息为:', callBackPayParams)
getPayUrlByNextStepParams(JSON.parse(callBackPayParams).extraParams, payType) // TODO: 更新信息之后重新进行支付
}
下单的参数直接传入到getPayUrlByNextStepParams 总线方法中即可,后续会根据订单的状态和结果进行执行结果
import { getPayUrl, insurancePay } from '@/apis/transaction.js'
引入一些拉起微信支付和签约的参数,getPayUrl 获取下单接口的参数 insurancePay 获取小程序支付参数的接口
import { contractSigning, appletPay, getParamByUrl, silentLogin } from '@/utils/tools.js'
contractSigning : 小程序的纯签约
appletPay : 小程序纯支付
getParamByUrl : 根据 URL 获取到锚点后的参数
silentLogin : 小程序静默登录封装