更新记录
1.0.0(2026-09-04)
银联 APP 综合支付
平台兼容性
uni-app(3.91)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
uni-app x(3.91)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ |
lxs-unionpay-app · 莉先生银联 APP 综合支付 UTS 插件
莉先生银联 APP 综合支付(银联商务 UMS 移动支付 V3.1.8) 的 uni-app UTS 原生插件封装,覆盖 Android / iOS / 鸿蒙(HarmonyOS) 三端。
封装基于官方 SDK 原生接口:
- Android:
com.chinaums.pppay.unify.UnifyPayPlugin- iOS:
UMSPPPayUnifyPayPlugin(UMSPosPayOnly)- 鸿蒙:
UMSPayPlugin(qmf_ppplugin_oh_har)
目录结构
lxs-unionpay-app/
├── package.json
├── README.md
├── example/pages/index.vue # 调用示例
└── utssdk/
├── index.uts # 对外类型 + 默认实现
├── android.uts # Android 桥接(Kotlin)
├── ios.uts # iOS 桥接(Swift)
├── ohos.uts # 鸿蒙桥接(ArkTS)
├── android/libs/
│ ├── qmf-ppplugin-android-3.1.8.aar
│ ├── UPPayAssistEx.jar # 云闪付
│ └── jniLibs/<abi>/libentryexpro.so
├── ios/UMSPosPayOnly.framework/ # .a + 头文件 + Info.plist
└── ohos/libs/qmf_ppplugin_oh_har_3.1.8.har
使用方式
将整个 lxs-unionpay-app 目录放入你的 uni-app 工程的 uni_modules/ 下,然后按工程类型引用。
⚠️ 普通 uni-app 与 uni-app x 的调用方式不同,别混用。 裸模块
import只在 uni-app x 下可用;普通 uni-app 用uni.requireUTSPlugin()。 判断依据:package.json里是@dcloudio/uni-app-plus(普通)还是@dcloudio/uni-app-x。
普通 uni-app(vue3,绝大多数工程)
// 字符串必须原样写死字面量,编译器靠它把插件打进基座,不能提取成常量
const unionpay = uni.requireUTSPlugin('lxs-unionpay-app')
// 1) 普通渠道(微信/支付宝/小程序等)
const res = await unionpay.pay({
channel: 'wechat', // wechat | alipay | wechatMini | alipayMini | aliSdk
appPayRequest: '<后台下单返回的 appPayRequest JSON 字符串>'
})
console.log(res.resultCode, res.resultInfo)
// 2) 云闪付
const res2 = await unionpay.cloudPay({ tn: '<后台返回的 tn>', serverMode: '00' })
uni-app x
import { pay, cloudPay } from 'lxs-unionpay-app'
const res = await pay({ channel: 'wechat', appPayRequest: '<...>' })
const res2 = await cloudPay({ tn: '<...>', serverMode: '00' })
💡 无论哪种方式,集成 UTS 插件后都必须重新制作一次自定义调试基座, 否则原生代码不在基座里,运行时会拿不到插件。
| 参数 | 说明 |
|---|---|
channel |
wechat 微信APP / alipay 支付宝直连 / wechatMini 微信小程序 / alipayMini 支付宝小程序 / aliSdk 支付宝间连原生 / unionpay 云闪付 |
appPayRequest |
商户后台下单后应答中的 appPayRequest 字段(JSON 字符串,原样透传) |
tn |
云闪付下单报文中 appPayRequest 内的 tn 码 |
serverMode |
云闪付接入模式,00 正式 / 01 测试(默认 00) |
⚠️
resultCode === '0000'仅表示 SDK 成功发起支付,最终是否支付成功必须以商户后台的异步通知或查单接口为准,切勿以客户端返回作为发货依据。
各端必须完成的宿主集成
Android
UnifyPayPlugin的微信结果回调依赖WXEntryActivity:在 App 包名对应路径下建立wxapi/WXEntryActivity.java并在AndroidManifest.xml配置android:exported="true"、android:launchMode="singleTask"、android:taskAffinity="应用包名"。-
云闪付(关键,必须接):
UPPayAssistEx.startPay的支付结果通过宿主Activity.onActivityResult返回,UTS 无法自动拦截,必须手动桥接,否则前端cloudPay()的 Promise 永远 pending、拿不到结果。 在 uni-app 业务工程的App-Android(离线 / 自定义基座)中,找到主Activity(继承IOUniActivity的类,通常叫PandoraEntry),在其onActivityResult里调用插件导出的onCloudPayResult:import android.content.Intent; // 包名规则:插件 id(lxs-unionpay-app)转下划线 → lxs_unionpay_app + 文件名 android + "Kt" import uts.sdk.plugins.lxs_unionpay_app.androidKt; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 把云闪付结果转交 UTS 插件,插件据此 resolve cloudPay() 的 Promise androidKt.onCloudPayResult(requestCode, resultCode, data); }⚠️ 若 import 报包名错误,先编译一次,到
unpackage/.../uts/sdk/plugins/lxs_unionpay_app/确认实际类名;或用反射兜底(见example/native/CloudPayAndroidActivity.java)。 完整可复制模板:example/native/CloudPayAndroidActivity.java。 - 云闪付需
libentryexpro.so(已在jniLibs内置全架构)。
iOS
- 集成微信 SDK:
UMSPosPayOnly头文件import <WXApi.h>,需在 iOS 工程链接WechatOpenSDK(libWeChatSDK),并在AppDelegate中调用:[UMSPPPayUnifyPayPlugin registerApp:@"微信AppId" universalLink:@"你的UniversalLink"];并在
openURL/continueUserActivity中调用对应的handleOpenURL:/handleOpenUniversalLink:。 - 支付宝小程序 / 间连支付宝 / 云闪付回调需按官方文档在
AppDelegate转发openURL。 - 在
Info.plist配置CFBundleURLTypes(URL Scheme),插件会自动读取第一个 Scheme 用于aliSafePay/ 云闪付。 - 云闪付 iOS 端结果通过
callbackBlock自动回到cloudPay()的 Promise,宿主只需把openURL/Universal Link转发给UMSPPPayUnifyPayPlugin(见example/native/CloudPayIOSAppDelegate.m):- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { [UMSPPPayUnifyPayPlugin handleOpenURL:url]; return YES; }
鸿蒙(HarmonyOS)
- 在
EntryAbility中按官方 demo 处理回调:// 云闪付 if (want?.uri?.includes('uppayresult')) { UMSPayPlugin.getInstance(ctx).handleUMSPayResult(UMSPayChannel.UnionPay, want) } // 支付宝小程序 / 微信小程序 if (want?.uri?.includes('qmfpppay://backfromalipay')) { UMSPayPlugin.getInstance(ctx).handleUMSPayResult(UMSPayChannel.AliMini, want) } UMSPayPlugin.getInstance(ctx).handleUMSPayResult(UMSPayChannel.WechatMini, want) - 微信小程序需
registerOnWXRespCallback/unregisterOnWXRespCallback(见官方 demoIndex.ets)。 qmf_ppplugin_oh_har的.har已放在utssdk/app-harmony/libs/。- 云闪付结果回调模板见
example/native/CloudPayHarmonyEntryAbility.ets(在EntryAbility的onCreate/onNewWant里处理uppayresultURI)。
已知待你确认的点(按平台编译时可能需要微调)
- iOS 方法名:UTS 调用 ObjC 用「选择器拼接」命名(如
payWithPayChannelPayDatacallbackBlock)。若编译报找不到方法,可改写为 Swift 风格payWithPayChannel(_:payData:_:)。 - iOS 获取 UIViewController:
topViewController()用keyWindow.rootViewController遍历,必要时按你工程的实际窗口结构微调。 - Android 渠道常量值:直接引用
UnifyPayRequest.CHANNEL_*静态字段,无需手填数值;若 SDK 版本升级导致字段名变化请同步。 - UTS 全局对象名:
UTSAndroid/UTSOhos为 UTS 标准全局对象;个别 UTS 版本 API 命名若有差异,以你本机 HBuilderX 版本为准。
故障排查:自定义调试基座里「检测不到插件」
症状:制作自定义调试基座后,getPluginStatus() 报「插件方法缺失 / 基座未包含该插件」,
或 android_debug.apk 里搜不到 libentryexpro.so。
1. 先验证基座里到底有没有(最硬的判据)
# 有 so / aar / jar → 插件进去了;一条都没有 → 没进去
unzip -l unpackage/debug/android_debug.apk | grep -iE "entryexpro|chinaums|unionpay|UPPay"
2. 先分清你用的是 uni-app 还是 uni-app x
这是最容易踩的坑,两种工程的 UTS 插件调用方式完全不同。
普通 uni-app(vue3 + @dcloudio/uni-app-plus) |
uni-app x(@dcloudio/uni-app-x) |
|
|---|---|---|
| 调用方式 | uni.requireUTSPlugin('插件id') |
import { xxx } from '插件id' |
| 平台条件编译 | APP-PLUS / APP-PLUS-NVUE / APP-NVUE |
APP-ANDROID / APP-IOS / APP-HARMONY |
| UTS 文件后缀 | 业务代码用 .js / .vue |
.uts / .uvue |
判定方法:看 package.json 的依赖是 @dcloudio/uni-app-plus 还是 @dcloudio/uni-app-x。
3. 普通 uni-app 下的正确写法
// 字符串字面量必须原样写死,不能提取成常量(编译器只扫描字面量)
const plugin = uni.requireUTSPlugin('lxs-unionpay-app')
await plugin.cloudPay({ tn, serverMode: '00' })
requireUTSPlugin 有两个作用:
- 运行时:返回
utssdk/<平台>/index.uts导出的对象(pay/cloudPay/onCloudPayResult) - 编译期:uni-app / HBuilderX 在做自定义基座和云打包时,静态扫描这个字符串字面量, 命中就把插件的原生代码(aar / jar / so / framework / har)注册进原生工程
4. 已验证行不通的写法(别再试)
| 写法 | 结果 |
|---|---|
import { pay } from 'lxs-unionpay-app' |
构建直接失败:[vite]: Rollup failed to resolve import "lxs-unionpay-app"(裸模块 id 是 uni-app x 专用) |
import { pay } from '../uni_modules/.../utssdk/app-android/index.uts' |
不报错,但只当普通 .uts 源文件处理,不注册插件、不合并 build.gradle、不拷贝 libs → 基座里没有 so |
用 #ifdef APP-ANDROID 包裹 import |
普通 uni-app 下条件恒假,import 整段被剔除,pay 变成未定义 |
vite.config.js 里给裸模块配 alias(按 UNI_PLATFORM 切平台目录) |
走错方向;UNI_PLATFORM 真实取值是 app / app-android / ...,不是 app-plus,判断恒 false 会让 alias 对 App 平台也生效,把模块定死到 utssdk/index.uts(reject 实现) |
DCloud 官方对 import 方式还有一条硬性要求:只能 import 到插件根目录, 不能指到
utssdk/内部的具体文件。
5. 改完必须做的清理
自定义基座有缓存,不清理会一直用旧的:
- 删除
unpackage/debug/与unpackage/cache/(至少删掉android_debug.apk) - HBuilderX:
运行 → 运行到手机或模拟器 → 制作自定义调试基座 - 打完再用第 1 步的命令验证一遍
6. 还要看控制台
如果 utssdk/app-android/index.uts 编译成 Kotlin 时报错(例如
com.chinaums.pppay.unify.UnifyPayPlugin 无法解析),HBuilderX 会静默跳过该插件继续出包,
表现就是「基座里没有插件」。所以制作基座时务必把控制台日志看完,搜 uts / lxs_unionpay / error。

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 0
赞赏 0
下载 12562103
赞赏 1948
赞赏
京公网安备:11010802035340号