【HarmonyOS】鸿蒙应用实现微信支付-最新版
一、前言
最近做了鸿蒙应用集成微信支付的功能,踩了不少坑,整理了一下完整流程和注意事项,希望能帮到有需要的同学。
1、微信开放平台配置应用信息: 在接入过程之前,我们需要在微信开放平台,注册自己的应用,开启支付权限。理论上这些都应该是运营提前做好,不过在这里也事先讲一下。
需在微信开放平台完成移动应用的创建/配置,获取AppID并填写鸿蒙应用信息:
创建/修改应用 :进入「管理中心 - 移动应用」,新建应用或在已有应用的「开发配置」中编辑鸿蒙信息。
填写关键信息 :
Bundle ID
:鸿蒙应用的包名(见下方链接)。
Identifier
:鸿蒙应用的appIdentifier(见下方链接)。
注意 :
若应用已上架Android/iOS市场,需选择「已上架至少一个应用市场」并填写备案号;仅鸿蒙未上架时,可按需选择上架状态。
「未上架任何应用市场」选项仅适用于Android、iOS、鸿蒙均未上架的情况,此类应用使用微信能力会受限,需谨慎选择。
Bundle ID: developer.huawei.com/consumer/cn...
appIdentifier: developer.huawei.com/consumer/cn...
2、鸿蒙应用接入微信OpenSDK: (1)sdk在OH三方库的地址:
typescript
// 把地址放到浏览器打开,查看最新的版本号,如我下方截图所示,是最近的最新版本信息。
https://ohpm.openharmony.cn/#/cn/detail/@tencent%2Fwechat_open_sdk
(2)接入方式: 在你项目的oh-package.json5的dependencies中配置sdk依赖:
typescript
{
"name": "demo",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
"@tencent/wechat_open_sdk": "1.0.14"
}
}
二、支付流程整体步骤:

简单说,整个支付流程大概是这样:
1、商户后端先调用微信的APP支付下单接口,拿到一个prepay_id
2、然后在商户的鸿蒙APP里,通过微信OpenSDK的sendReq方法调起微信,用户在微信里完成支付(或取消)
3、之后会跳转回商户APP,这时候前端会收到回调,一定要记得让后端调用查询订单接口确认状态(别光信回调里的信息)
4、支付成功的话,微信还会发个支付成功的回调通知给后端
5、最后就是对账和可能的退款操作了。
三、详细步骤拆解

1、 拿到prepay_id是第一步,用于商户下单:
首先得调用微信的APP支付下单接口,核心是获取prepay_id(预支付交易会话标识),这是后面调起支付的关键。
这里有两个时间点要特别注意:
time_expire:可以设置订单的支付结束时间。超过这个时间用户再支付,会提示"订单已超过最晚支付时间",这时候商户得做关单处理。如果不设置,默认订单7天内有效,7天后微信会自动关单。
prepay_id有效期:这个ID只有2小时!过期了就得用原来的下单参数重新调用接口拿新的,别想着复用。
2、OpenSDK接入,来调起支付:
拿到prepay_id后,就该调起微信支付了。首先得接入微信的OpenSDK(建议用最新版,兼容性更好),然后通过OpenSDK的sendReq方法调起微信支付页面。
步骤1:创建WXApi实例
typescript
import * as wxopensdk from '@tencent/wechat_open_sdk';
// 传入移动应用的AppID(注意:需使用移动应用AppID,不可用小程序AppID)
export const WXApi = wxopensdk.WXAPIFactory.createWXAPI(APP_ID);
步骤2:实现回调处理
typescript
// 实现微信数据回调接口
class WXApiEventHandlerImpl implements wxopensdk.WXApiEventHandler {
private onReqCallbacks: Map<OnWXReq, OnWXReq> = new Map();
private onRespCallbacks: Map<OnWXResp, OnWXResp> = new Map();
// 注册/取消注册回调
registerOnWXReqCallback(on: OnWXReq) { this.onReqCallbacks.set(on, on); }
unregisterOnWXReqCallback(on: OnWXReq) { this.onReqCallbacks.delete(on); }
registerOnWXRespCallback(on: OnWXResp) { this.onRespCallbacks.set(on, on); }
unregisterOnWXRespCallback(on: OnWXResp) { this.onRespCallbacks.delete(on); }
// 处理来自微信的请求
onReq(req: wxopensdk.BaseReq): void {
this.onReqCallbacks.forEach(on => on(req));
}
// 处理微信返回的响应
onResp(resp: wxopensdk.BaseResp): void {
this.onRespCallbacks.forEach(on => on(resp));
}
}
export const WXEventHandler = new WXApiEventHandlerImpl();
步骤3:发送登录请求
typescript
// 构建登录请求参数
let req = new wxopensdk.SendAuthReq();
req.scope = 'snsapi_userinfo'; // 授权范围
req.state = 'none'; // 自定义状态值
req.transaction = 'test123'; // 事务标识
// 发送请求(context为UIAbilityContext,从组件中获取)
let finished = await WXApi.sendReq(context, req);
// finished为true表示跳转微信成功,false可能因微信未安装导致
步骤4:在EntryAbility中处理回调
typescript
export default class EntryAbility extends UIAbility {
onCreate(want: Want, _launchParam: AbilityConstant.LaunchParam): void {
this.handleWeChatCallIfNeed(want);
}
onNewWant(want: Want, _launchParam: AbilityConstant.LaunchParam): void {
this.handleWeChatCallIfNeed(want);
}
// 处理微信返回的Want数据
private handleWeChatCallIfNeed(want: Want) {
WXApi.handleWant(want, WXEventHandler);
}
}
3、 用户支付:回调处理和订单确认是关键
用户在微信里完成支付或取消支付后,会跳转回商户APP,这时候前端会收到OpenSDK的onResp回调。划重点:千万别只靠这个回调就判断支付状态! 必须让后端调用查询订单API,确认真实的订单状态后再处理业务(比如展示支付结果、更新系统订单状态)。
如果需要限制用户支付时间,有两种方式:
- 下单时用time_expire参数设置结束时间,超时后做关单;
- 自己系统里做倒计时,超时后主动关单。
另外,如果想在有效期内主动关闭未支付的订单,先查一下订单状态,确认是未支付(NOTPAY)后,调用关单接口就行,关单后订单就成失败终态了。
请求支付:
typescript
IWXAPI api;
let req = new wxopensdk.PayReq
req.appId = 'wxd930ea5d5a258f4f'
req.partnerId = '1900000109'
req.prepayId = '1101000000140415649af9fc314aa427'
req.packageValue = 'Sign=WXPay'
req.nonceStr = '1101000000140429eb40476f8896f4c9'
req.timeStamp = '1398746574'
req.sign = 'oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd7vaRvkYD7rthRAZ\/X+QBhcCYL21N7cHCTUxbQ+EAt6Uy+lwSN22f5YZvI45MLko8Pfso0jm46v5hqcVwrk6uddkGuT+Cdvu4WBqDzaDjnNa5UK3GfE1Wfl2gHxIIY5lLdUgWFts17D4WuolLLkiFZV+JSHMvH7eaLdT9N5GBovBwu5yYKUR7skR8Fu+LozcSqQixnlEZUfyE55feLOQTUYzLmR9pNtPbPsu6WVhbNHMS3Ss2+AehHvz+n64GDmXxbX++IOBvm2olHu3PsOUGRwhudhVf7UcGcunXt8cqNjKNqZLhLw4jq\/xDg=='
api.sendReq(context: common.UIAbilityContext, req)
支付返回
typescript
onResp(resp: wxopensdk.BaseResp): void {
Log.i(kTag, "onResp:%s", JSON.stringify(resp))
this.onRespCallbacks.forEach((on) => {
on(resp)
})
}
4、 对账和退款
对账可以参考微信的"账单产品介绍",按官方指引来就行。
如果需要退款,调用退款接口即可,不过要注意:只有支付成功1年内的订单才能申请退款。
三、订单状态总览:
最后梳理下订单状态的流转逻辑,这个理清楚了,业务处理就不容易出错:
1、下单成功后,订单状态是未支付(NOTPAY),这时候用户可以支付
2、用户支付成功,状态变成支付成功(SUCCESS);如果支付失败,还是NOTPAY
3、未支付的订单,要么超过7天(或设置的time_expire)被自动关单,要么被商户主动关单,状态会变成已关闭(CLOSED)
4、 支付成功(SUCCESS)的订单,申请退款后,状态会变成转入退款(REFUND),退款状态可以查退款单确认
5、有三个终态要记牢:CLOSED(已关闭)、SUCCESS(支付成功)、REFUND(转入退款),到了这三个状态就不会再变了。
常见问题
1、如何判断微信是否安装?
通过WXApi.isWXAppInstalled()
判断,需在module.json5
中添加相关声明(参考「使用canOpenLink判断应用是否可访问」)。
2、登录失败:Bundle ID校验不通过?
原因:鸿蒙应用信息提交后未审核通过(审核中/驳回),或审核通过但appid + identifier + bundleId
不匹配。
解决:重新提交审核,确保信息与微信开放平台配置一致。
3、第三方应用信息校验失败?
可能原因:
createWXAPI
传入的AppID错误(需为移动应用AppID,不可用小程序/AppID);
微信开放平台配置的Identifier
与应用实际appIdentifier
不一致。
建议:检查AppID正确性,确认Identifier
匹配,避免使用IDE自动生成的测试签名(可申请测试用移动应用账号)。
4、App如何接收微信返回的数据?
需配置action为wxentity.action.open
,并通过实现WXApiEventHandler
的onReq
函数处理数据(参考代码示例)。
typescript
// 官方文档链接参见:
https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Pay/Android.html