# uni-app x 蒸汽模式接入

需要 vk-uni-pay ≥ 1.18.0、HBuilderX ≥ 5.33,建议下载 1.18.1 及以上版本的示例项目。本文以 1.18.1 为例,仅适用于 uni-app x 蒸汽模式。

云端支付配置、云函数和数据库与 uni-app 共用,主要区别在前端页面写法。

# 1、导入示例项目

在 HBuilderX 中从插件市场 (opens new window)导入 uni-app x 示例项目。导入时,HBuilderX 会自动将 manifest.json 替换为 uni-app x 配置,导入后的示例项目可以直接运行。

# 2、配置并体验支付

体验实际支付前,按示例项目运行教程完成云空间初始化、支付参数和小程序 AppID 等配置。App 支付还需填写自己的应用信息,详见App 配置。

示例首页已提供各项功能入口,对应页面如下:

功能 示例页面(位于 pages-x 目录)
功能入口 select/select.uvue
微信、支付宝支付、查询、退款、公众号授权及 H5 返回处理 index/index.uvue
商家扫用户付款码 index/codepay.uvue
转账、确认收款与免确认收款授权 index/transfer.uvue
微信小程序虚拟支付 wxpay-virtual/wxpay-virtual.uvue
鸿蒙 App 华为支付 huawei/huawei.uvue

# 3、接入自己的页面

将下面代码保存为 .uvue 页面并注册到 pages.json。示例使用默认 vk-pay 云函数,演示 App 原生支付、小程序支付和 PC 扫码支付;公众号授权、手机 H5 支付跳转返回请使用上方完整示例。

微信使用 provider: 'wxpay',支付宝使用 'alipay'。示例金额为 1 分,type: 'recharge' 对应示例的充值回调,实际项目请替换为自己的业务。

<template>
  <view class="pay-page">
    <button :disabled="busy" @click="createPayment()">支付 0.01 元</button>
    <button :disabled="busy || !outTradeNo" @click="queryPayment">我已支付,查询结果</button>
    <text>{{ message }}</text>
    <vk-uni-pay
      ref="payRef"
      v-model:status="vkPay.status"
      v-model:codeUrl="vkPay.codeUrl"
      v-model:qrcodeImage="vkPay.qrcodeImage"
      :query-payment-action="queryAction"
      :page-show="vkPay.pageShow"
      :polling="true"
    />
    <vk-uni-pay-qrcode-popup
      :status="vkPay.status"
      :code-url="vkPay.codeUrl"
      :qrcode-image="vkPay.qrcodeImage"
      :out-trade-no="outTradeNo"
      :total-fee="1"
      :provider="provider"
      @close="cancelPay"
      @query="queryPayment"
      @afresh="createPayment(true)"
    />
  </view>
</template>

<script setup lang="ts">
  const payRef = ref<any>(null);
  const provider = ref('wxpay'); // 微信:wxpay;支付宝:alipay
  // #ifdef MP-ALIPAY
  provider.value = 'alipay';
  // #endif
  const outTradeNo = ref('');
  const message = ref('等待支付');
  const busy = ref(false);
  const vkPay = reactive({ status: 0, codeUrl: '', qrcodeImage: '', pageShow: true });
  const queryAction = { name: 'vk-pay', action: 'pay/queryPayment', actionKey: 'action', dataKey: 'data' };
  let alive = true;
  onShow(() => {
    vkPay.pageShow = true;
  });
  onHide(() => {
    vkPay.pageShow = false;
  });
  onUnload(() => {
    alive = false;
    vkPay.pageShow = false;
  });

  function showError(error: any) {
    if (alive) message.value = error.msg || error.errMsg || error.message || '请求失败';
  }
  async function createPayment(reuseOrder = false) {
    if (!alive || !payRef.value || busy.value) return;
    busy.value = true;
    // 示例本地生成订单号;实际业务由云端确定订单号和金额。
    if (!reuseOrder || !outTradeNo.value) outTradeNo.value = 'test_' + Date.now();
    try {
      if (reuseOrder) {
        vkPay.status = 0;
        await nextTick(); // 先结束上次轮询,再使用原订单重新支付
      }
      await payRef.value.createPayment({
        action: { name: 'vk-pay', action: 'pay/createPayment', actionKey: 'action', dataKey: 'data' },
        data: {
          provider: provider.value,
          total_fee: 1,
          out_trade_no: outTradeNo.value,
          subject: '测试订单',
          type: 'recharge',
        },
        create: (res: any) => {
          if (!alive) return;
          outTradeNo.value = res.out_trade_no || outTradeNo.value;
          message.value = '订单已创建,请完成支付';
        },
        success: () => {
          if (alive) message.value = '支付成功';
        },
        fail: showError,
        cancel: () => {
          if (alive) message.value = '用户取消支付';
        },
      });
    } catch (error) {
      showError(error);
    } finally {
      busy.value = false;
    }
  }
  async function queryPayment() {
    if (!alive || !payRef.value || busy.value || !outTradeNo.value) return;
    busy.value = true;
    try {
      await payRef.value.queryPayment({
        data: { out_trade_no: outTradeNo.value },
        needAlert: false,
        success: () => {
          if (!alive) return;
          vkPay.status = 2; // 手动查单成功后,更新页面状态并关闭二维码弹窗
          message.value = '支付成功';
        },
        fail: showError,
      });
    } catch (error) {
      showError(error);
    } finally {
      busy.value = false;
    }
  }
  function cancelPay() {
    if (vkPay.status === 2) return;
    vkPay.status = 0;
    vkPay.codeUrl = '';
    vkPay.qrcodeImage = '';
    message.value = '已关闭展示,可继续查询该订单';
  }
</script>

<style scoped>
  .pay-page {
    padding: 16px;
  }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

三个组件通过 easycom 自动引入,保留完整插件目录即可,不需要手动导入 .vue 文件。ref、reactive 和页面生命周期沿用 uni-app x 示例写法;按钮点击时通过 payRef.value 调用组件方法。

注意这三个结果的区别:

  • create:订单创建成功,还没有确认付款。
  • await createPayment():发起流程返回,不代表付款成功。
  • success 或主动查单成功:确认付款成功;发货、充值等业务仍由云端回调处理。

关闭二维码只结束前端展示,不会撤销云端订单;弹窗中的“重新支付”继续使用原订单号。主动查单成功后,需要像示例一样设置 status = 2。加载提示、等待业务回调等参数见组件文档。

# 各平台注意事项

# App

在 manifest 的目标平台配置中勾选使用的微信或支付宝支付模块:

平台 支付模块所在节点 微信支付还需配置
Android app-android.distribute.modules.uni-payment 微信开放平台的包名、签名
iOS app-ios.distribute.modules.uni-payment AppID、Bundle ID、Universal Link
鸿蒙 app-harmony.distribute.modules.uni-payment 对应微信开放平台应用信息

uni-payment 节点内按需添加 wxpay、alipay;鸿蒙使用华为支付时添加 huawei。配置步骤见 Android (opens new window)、iOS (opens new window)、鸿蒙 (opens new window)官方文档。华为支付还需云端配置及请求参数 biz_type。

保留插件内 utssdk 目录,它提供 App 打开支付链接的能力。修改原生支付模块或 UTS 插件后,重新制作包含这些能力的自定义基座或安装包再测试。

# 支付宝转 H5

云端配置 alipayAppPayToH5Pay: true 后,组件会按返回参数尝试唤起支付宝;打开失败且返回了二维码时,会回退到二维码展示。页面保留二维码弹窗和查单按钮即可。

此方式不保证自动返回 App。用户返回后,通过查单确认支付结果;page-show 与页面 onShow、onHide 绑定,隐藏时暂停轮询。App 的 return-url 仅用于 H5 支付链接的网页返回地址,不等于 App 原生回跳配置。

# 小程序

组件默认自动获取小程序 OpenID,需配置 uni-id 并部署示例的 code2SessionWeixin 或 code2SessionAlipay 接口。自行传入 OpenID 时,设置 :auto-get-openid="false",在 createPayment 的 data 中传 openid。

微信虚拟支付使用 provider: 'wxpay-virtual',还需开通对应能力并配置小程序消息推送。小程序不能直接打开外部 App 的 H5 支付链接,跨渠道扫码应通过 needQRcode 获取二维码。

# Web 与公众号

PC 使用二维码展示和轮询;公众号需先授权获取公众号 OpenID,不能使用小程序的 OpenID 代替。查看公众号配置

微信 H5 支付默认返回当前网页,也可设置 return-url。返回页读取 out_trade_no 后查单,不可仅凭跳转成功认定已付款。完整官方支付示例已处理 URL 查询串及 hash 路由中的返回参数。

# 转账与确认收款

云端转账接口共用。微信小程序直接调用 uni.requestMerchantTransfer;Android、iOS、鸿蒙 App 需导入 uni-requestMerchantTransfer 插件 (opens new window),在包含该能力的基座中调用,参数使用云端返回的 options。

x 转账示例的确认收款和免确认收款授权支持上述 App 及微信小程序。微信公众号确认收款沿用原文档的 WeixinJSBridge 流程,普通浏览器和支付宝小程序不适用该示例的微信确认功能。