前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >代码记录-封装一套小程序支付和纯签约以及静默授权登录流程

代码记录-封装一套小程序支付和纯签约以及静默授权登录流程

作者头像
何处锦绣不灰堆
发布2023-10-18 17:42:34
3410
发布2023-10-18 17:42:34
举报
文章被收录于专栏:农历七月廿一
静默授权

代码语言:javascript
复制
/**
 * @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 }
}
小程序的支付和纯签约流程
代码语言:javascript
复制
/**
 * @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 总线方法中即可,后续会根据订单的状态和结果进行执行结果

代码语言:javascript
复制
import { getPayUrl, insurancePay } from '@/apis/transaction.js'
引入一些拉起微信支付和签约的参数,getPayUrl 获取下单接口的参数    insurancePay 获取小程序支付参数的接口 
代码语言:javascript
复制
import { contractSigning, appletPay, getParamByUrl, silentLogin } from '@/utils/tools.js'
contractSigning : 小程序的纯签约
appletPay : 小程序纯支付
getParamByUrl : 根据 URL 获取到锚点后的参数
silentLogin : 小程序静默登录封装
代码执行流程图
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 静默授权
  • 小程序的支付和纯签约流程
  • 代码解释
  • 代码执行流程图
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档