支付流程

Wednesday, June 7, 2023

支付功能

  1. 支付方法的封装: 在我们的应用中,我们将支付方法封装起来,使其可以在任意组件和页面中轻松调用。这不仅简化了支付功能的使用,还将大量常用的业务逻辑封装在内,比如交易结果轮询和监听用户操作等。

  2. 调用方式: 调用支付方法时,需要传入订单参数、额外参数和支付参数。订单参数和额外参数根据具体业务需求来决定,比如在特定时间点购买时可能需要额外参数。支付参数则包含了是否锁定订单类型(比如情侣应用中需要考虑两人同时支付的情况)、是否显示交易提醒Toast,以及当前组件或页面的上下文(this)。

  3. Promise 处理: 支付方法返回一个 Promise 对象。当方法被调用时,会先将 resolvereject 函数保存到变量 _delayPayResolve_delayPayReject 中,这样在不同的支付状态下可以方便地调用它们,这两个新的resolve和reject函数体内还包含清理变量的 _restorePayParams 方法用于清除临时变量(如 lockorderId、以及本次的 resolvereject)。

  4. 支付流程: 在我们的应用中,支持“情侣币”或微信/QQ钱包等线上支付方式。系统会优先尝试使用“情侣币”进行结算。提交交易请求后,系统会同步返回一个交易ID,并通过 checkPaymentResult 方法进行交易结果轮询。根据结果执行 _delayPayResolve_delayPayReject 来结束交易流程,回到组件或页面内继续原有的业务逻辑。

  5. 处理交易失败: 如果交易失败,根据错误码不同进行处理。如果是余额不足,会引导用户进行现金支付;如果是其他错误,则调用 _delayPayReject 并返回组件或页面,提示交易失败。

  6. 现金支付处理

    我们通过外部网页完成现金支付。当调用现金支付方法时,需要传入上下文(this)。在支付方法内,首先将交易ID和地址拼接成一个URL,然后对传入的上下文进行hook操作,最后打开外部网页进行支付。

  7. 处理 onShow 生命周期

    1. 由于支付是在小程序外进行,没有明确的回调机制,因此我们依赖小程序的 onShow 生命周期方法来观测是否需要轮询交易结果。根据传入的上下文(this),判断是否存在 onShow 方法。如果存在,说明当前是在页面中。此时,需要将原 onShow 方法保存,然后重写 ctx.onShow,首先添加轮询交易结果的 checkPaymentResult 方法,然后执行原来的 onShow 逻辑,最后将onShow 恢复为原方法。
    2. 如果上下文中没有 onShow 方法,说明是在组件内。由于组件自身没有 onShow 方法,但可以通过 pageLifetimes 与页面生命周期关联,所以我们会使用 Behavior(类似于Vue中的 mixins)来引入支付文件中的 checkPaymentBehavior。这段复用代码的逻辑是,当页面触发 onShow 时,会调用一个支付文件内的钩子函数。正常状态下,该函数是一个空函数,只有在支付逻辑调用时,会在钩子函数内加入 checkPaymentResult 方法,查询结束后再将钩子函数复原。