Skip to content

所有支付相关内容

  1. 游泳馆 办卡 微信支付
  2. 游泳馆 单次票 微信支付
  3. 羽毛球 办卡 微信支付
  4. 羽毛球 订场 一卡通支付
  5. 羽毛球 订场 会员卡支付
  6. 羽毛球 订场 微信支付
  7. 足球馆 办卡 微信支付
  8. 足球馆 订场 会员卡支付
  9. 足球馆 订场 微信支付
  10. 充值 一卡通 微信支付
  11. 充值 游泳卡 微信支付
  12. 充值 羽毛球卡 微信支付
  13. 充值 足球卡 微信支付
  14. 体测机 获取报告 微信支付
  15. 赛事活动 报名费 微信支付

关于微信支付

后端返回的 微信支付格式一致,皆为

ts
export interface IResPay {
  appId: string //'wxa9462c49dd468b45'
  nonceStr: string //'gYAObidSwEi7DYsx'
  packageValue: string //'prepay_id=wx0410242604233355fef688a2db13730001'
  paySign: string //'DCCCF08E293FCEF18D980F2C6B885612'
  signType: string //'MD5'
  timeStamp: string //'1730687066'
}

在此基础上,经过多次思考,最终是把微信支付进行统一封装

微信支付的唤起方式

ts
interface IMpWxPay {
  /**
   * 公众号ID,由商户传入
   */
  appId: string
  /**
   * 时间戳
   */
  timeStamp: string
  /**
   * 随机串
   */
  nonceStr: string
  /**
   * prepay_id
   */
  package: string
  /**
   * 微信签名方式,如 RSA
   */
  signType: string
  /**
   * 微信签名
   */
  paySign: string
}

export const wxMpPay = (wxPay: IMpWxPay) => {
  // package 为 js 关键字,不能为变量名
  const { appId, timeStamp, nonceStr, package: pg, signType, paySign } = wxPay
  if (!appId) return Promise.reject('缺少appId')
  if (!timeStamp) return Promise.reject('缺少timeStamp')
  if (!nonceStr) return Promise.reject('缺少nonceStr')
  if (!pg) return Promise.reject('缺少package')
  if (!signType) return Promise.reject('缺少signType')
  if (!paySign) return Promise.reject('缺少paySign')

  const param = {
    appId, //公众号ID,由商户传入
    timeStamp, //时间戳,自1970年以来的秒数
    nonceStr, //随机串
    package: pg,
    signType, //微信签名方式:
    paySign //微信签名
  }

  // console.log('微信支付 WeixinJSBridge.invoke 参数 > ', param)

  return new Promise((resolve, reject) => {
    if (!WeixinJSBridge) return reject('WeixinJSBridge 不存在')
    // @ts-ignore
    WeixinJSBridge.invoke(
      'getBrandWCPayRequest',
      param,
      // @ts-ignore
      function (res) {
        const isPaySuccess = res.err_msg === 'get_brand_wcpay_request:ok'
        // console.log('微信支付结果', isPaySuccess, res)
        if (isPaySuccess) {
          resolve(res)
        } else {
          reject(res)
        }
      }
    )
  })
}

针对微航后端进一步的封装

ts
import type { IResPay } from '@/api/type'
import { wxMpPay } from '@/util/weixin'
import { ref } from 'vue'

// ----------------------------------------------------------------
// 微信支付 Hooks
// ----------------------------------------------------------------

// 这个type的意义是:支付结果为多状态设计
// 1. 是否 可以支付
// 2. 是否 支付成功
// 3. 如果有需求变动,可以增加其他
export interface IWxPayResult {
  message: string
  /**
   * 是否 可以支付
   *
   * 因为 server 提供给的支付参数并不一定有
   */
  isCanPaid: boolean
  /**
   * 是否 支付成功
   */
  isPaySuccess: boolean
}

export const useWxPay = () => {
  const payDate = ref<IPayDataV2>(createWxPayV2Data())

  /**
   * 是否有支付缓存
   *
   * 微信支付 参数可以 多次使用,如果存在缓存可以直接支付
   */
  const hasPayCache = () => payDataCheck(payDate.value)

  const invokePay = async (data?: IResPay): Promise<IWxPayResult> => {
    let myData: IPayDataV2 | undefined = undefined

    // 如果 传入 data,将 支付数据记录下来
    if (data) {
      const { packageValue, ...other } = data

      myData = {
        ...other,
        package: packageValue
      }

      if (payDataCheck(myData)) {
        payDate.value = myData
      }
    }

    const payConf: IPayDataV2 = myData || payDate.value

    const result: IWxPayResult = {
      message: 'default value',
      isCanPaid: false,
      isPaySuccess: false
    }

    if (!payDataCheck(payConf)) {
      result.message = 'API返回支付参数异常'
      return result
    }

    try {
      result.isCanPaid = true

      //   const res =
      await wxMpPay(payConf)

      result.isPaySuccess = true
      result.message = '支付成功'

      return result
    } catch (error: any) {
      // get_brand_wcpay_request:cancel
      if (error.err_msg === 'get_brand_wcpay_request:cancel') {
        result.message = '取消支付'
      } else {
        result.message = '支付失败:' + error?.message || error.err_msg
      }

      return result
    }
  }

  return {
    payDate,
    hasPayCache,
    invokePay
  }
}

/**
 * 微信支付 v2 数据
 *
 */

export interface IPayDataV2 {
  appId: string
  timeStamp: string
  nonceStr: string
  package: string
  signType: string
  paySign: string
}

/**
 * 创建一个value为空的 微信支付 数据
 */
export function createWxPayV2Data(): IPayDataV2 {
  return {
    appId: '', //公众号ID,由商户传入
    timeStamp: '', //时间戳,自1970年以来的秒数
    nonceStr: '', //随机串
    package: '',
    signType: '', //微信签名方式:
    paySign: ''
  }
}

/**
 * 检查 支付信息 是否有效
 */
function payDataCheck(data: IPayDataV2) {
  if (!data || typeof data !== 'object') return false

  const { appId, timeStamp, nonceStr, package: pack, signType, paySign } = data

  return appId && timeStamp && nonceStr && pack && signType && paySign
}

最终效果:

ts
import { useWxPay } from '@/hook/useWxPay'


const { hasPayCache, invokePay } = useWxPay()

// 现目前没有使用
// 重复支付在用户修改了订单信息有问题,所以设计了,但是没有使用
if (hasPayCache()) {
 return invokePay()
}

reqPlayTicket({
  couponId: selectCoupon.value?.id,
  couponMoney: selectCoupon.value?.amount,

  originalPrice: amount.value,
  priceTotal: total.value,
  num: order.singleUserInputInfo.count,
  ticketId,
  venueId
})
  .then((res) => invokePay(res.data))
  .then(({ message, isCanPaid, isPaySuccess }) => {
    if (!isCanPaid || !isPaySuccess) return showError(message)

    toResultPage()
  })
  .catch((e) => {
    console.error(e)
    showError(e.message || '获取支付信息失败')
  })

关于 重新支付/微信支付

ts
/**
 * 重新支付
 */
export const useRePay = () => {
  const { invokePay } = useWxPay()

  const rePay = async (order: IOrder): Promise<IWxPayResult> => {
    if (!order.raw) throw new Error('订单数据异常')

    const { tradeType, orderType, orderStatus } = order.raw

    console.log('重新支付')
    console.log('tradeType 交易类型 1体测机 2赛事活动 3一卡通 4羽毛球 5足球馆 6游泳馆')
    console.log({ tradeType, orderType })

    const payFunc = (res: IResPayOrder) => {
      if (res.code !== 200) throw new Error(res.msg)
      return invokePay(res.data)
    }

    // 体测机
    if (tradeType === 1) {
      return rePayCheckup(order.raw).then(payFunc)
    }

    // 赛事活动报名
    if (tradeType === 2) {
      return rePayActivity(order.raw).then(payFunc)
    }

    // 一卡通
    if (tradeType === 3) {
      return rePayOneCard(order.raw).then(payFunc)
    }

    // 羽毛球
    if (tradeType === 4) {
      console.log('羽毛球 orderType 1=线下订场,2=办卡,3=充值,4=延期,5=锁场,6=微信订场')

      // 办卡
      if (orderType === 2) {
        return rePayBadmintonApplyCard(order.raw).then(payFunc)
      }
      // 充值
      if (orderType === 3) {
        return rePayRechargeBadminton(order.raw).then(payFunc)
      }
      // 微信订场
      if (orderType === 6) {
        return rePayBadminton(order.raw).then(payFunc)
      }
    }

    // 游泳馆
    if (tradeType === 6) {
      console.log('游泳馆 orderType 订单类型(1售票,2办卡,3续卡,4退卡,5转卡,6冻卡,7解冻,8延期)')

      // 1 售票
      if (orderType === 1) {
        return rePaySwimBuyTicket(order.raw).then(payFunc)
      }

      // 2 办卡
      if (orderType === 2) {
        return rePaySwimCard(order.raw).then(payFunc)
      }

      // 3 续卡
      if (orderType === 3) {
        return rePayRenewSwimCard(order.raw).then(payFunc)
      }
    }

    // 足球馆
    if (tradeType === 5) {
      console.log('足球馆 orderType 订单类型(1售票,2办卡,3充值)')

      // 定场
      if (orderType === 1) {
        return rePayFootball(order.raw)
          .then((res) => {
            return { ...res, data: res.data.data }
          })
          .then(payFunc)
      }

      // 办卡
      if (orderType === 2) {
        return rePayFootballCard(order.raw)
          .then((res) => {
            return { ...res, data: res.data.data }
          })
          .then(payFunc)
      }

      // 充值
      if (orderType === 3) {
        return rePayRechargeFootballCard(order.raw).then(payFunc)
      }
    }

    throw new Error('未知类型:' + tradeType + ',orderType:' + orderType)
  }

  return { rePay }
}

具体 看 代码,这里提供一下具体的请求参数

ts
// 活动报名
function rePayActivity(order: IResOrderListRows) {
  const { orderNo } = order
  const wxStore = useWeixinStore()

  return reqActivityRePay({
    orderNo,
    openId: wxStore.openId
  })
}

// 一卡通 重新支付
function rePayOneCard(order: IResOrderListRows) {
  const { orderNo } = order
  const wxStore = useWeixinStore()

  return reqRePayOneCard({
    orderNo,
    openId: wxStore.openId,
    amount: order.payAmount
  })
}

function rePayCheckup(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePayCheckup({
    orderNo,
    openId: wxStore.openId,
    amount: payAmount
  })
}

// 羽毛球 定场 重新支付
function rePayBadminton(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  const param = {
    orderNo,
    realityMoney: payAmount,
    payType: 3 as 3,
    openId: wxStore.openId
  }
  return reqBadmintonPayOrder(param)
}

// 羽毛球 办卡 重新支付
function rePayBadmintonApplyCard(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePayBadmintonApplyCard({
    orderNo,
    openId: wxStore.openId,
    realityMoney: payAmount
  })
}

// 羽毛球 会员卡充值 重新支付
function rePayRechargeBadminton(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePayRechargeBadminton({
    orderNo,
    openId: wxStore.openId,
    amount: payAmount
  })
}

function rePaySwimBuyTicket(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePaySwimBuyTicket({
    orderNo,
    openId: wxStore.openId,
    priceTotal: payAmount
  })
}

function rePaySwimCard(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePaySwimBuyCard({
    orderNo,
    openId: wxStore.openId,
    payAmount
  })
}

// 游泳卡 充值
function rePayRenewSwimCard(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePayRechargeSwim({
    orderNo,
    openId: wxStore.openId,
    amount: payAmount
  })
}

// 足球馆 定场 重新支付
function rePayFootball(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePayFootball({
    orderNo,
    openId: wxStore.openId,
    price: payAmount
  })
}

function rePayFootballCard(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePayFootballCard({
    orderNo,
    openId: wxStore.openId,
    payAmount
  })
}

function rePayRechargeFootballCard(order: IResOrderListRows) {
  const { orderNo, payAmount } = order
  const wxStore = useWeixinStore()

  return reqRePayRechargeFootball({
    orderNo,
    openId: wxStore.openId,
    amount: payAmount
  })
}