【HarmonyOS】鸿蒙应用实现微信支付-最新版_鸿蒙微信支付弹窗
【HarmonyOS】鸿蒙应用实现微信支付-最新版
一、前言
最近做了鸿蒙应用集成微信支付的功能,踩了不少坑,整理了一下完整流程和注意事项,希望能帮到有需要的同学。
1、微信开放平台配置应用信息:
在接入过程之前,我们需要在微信开放平台,注册自己的应用,开启支付权限。理论上这些都应该是运营提前做好,不过在这里也事先讲一下。
需在微信开放平台完成移动应用的创建/配置,获取AppID并填写鸿蒙应用信息:
创建/修改应用:进入「管理中心 - 移动应用」,新建应用或在已有应用的「开发配置」中编辑鸿蒙信息。
填写关键信息:Bundle ID
:鸿蒙应用的包名(见下方链接)。Identifier
:鸿蒙应用的appIdentifier(见下方链接)。
注意:
若应用已上架Android/iOS市场,需选择「已上架至少一个应用市场」并填写备案号;仅鸿蒙未上架时,可按需选择上架状态。
「未上架任何应用市场」选项仅适用于Android、iOS、鸿蒙均未上架的情况,此类应用使用微信能力会受限,需谨慎选择。
Bundle ID:
https://developer.huawei.com/consumer/cn/doc/app/agc-help-createharmonyapp-0000001945392297
appIdentifier:
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-bundlemanager-bundleinfo-V5
2、鸿蒙应用接入微信OpenSDK:
(1)sdk在OH三方库的地址:
// 把地址放到浏览器打开,查看最新的版本号,如我下方截图所示,是最近的最新版本信息。https://ohpm.openharmony.cn/#/cn/detail/@tencent%2Fwechat_open_sdk
(2)接入方式:
在你项目的oh-package.json5的dependencies中配置sdk依赖:
{ \"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实例
import * as wxopensdk from \'@tencent/wechat_open_sdk\';// 传入移动应用的AppID(注意:需使用移动应用AppID,不可用小程序AppID)export const WXApi = wxopensdk.WXAPIFactory.createWXAPI(APP_ID);
步骤2:实现回调处理
// 实现微信数据回调接口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:发送登录请求
// 构建登录请求参数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中处理回调
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)后,调用关单接口就行,关单后订单就成失败终态了。
请求支付:
IWXAPI api;let req = new wxopensdk.PayReqreq.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)
支付返回
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
函数处理数据(参考代码示例)。
// 官方文档链接参见:https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Pay/Android.html