From 41bbdb2bff0a7cd6a8e2ce9e2e9a7165bcf288f5 Mon Sep 17 00:00:00 2001 From: Fury76 <7465355+Fury76@users.noreply.github.com> Date: Wed, 23 Sep 2026 13:18:15 +0800 Subject: [PATCH] fix(ohos): bind the WXApi event handler on registerApp so the first callback after cold start is not lost The WeChat HarmonyOS SDK (@tencent/wechat_open_sdk 1.0.15) dispatches responses to the handler it got in the most recent handleWant() call, and handleWant() is the only way to give it one. With current WeChat versions the SDK sends requests through openLink and delivers the response from the openLink completion callback via `this.eventHandler?.onResp(...)`, which never goes through onNewWant. fluwx only called handleWant() from onNewWant / attemptToResumeMsgFromWx, so after every cold start the handler was null and the first auth / pay response was dropped silently; later ones worked only because WeChat's return had triggered onNewWant once. - registerApp now binds the plugin as event handler through handleWant() with an empty Want. An empty Want carries no WeChat payload, so nothing is dispatched; the launch Want is still left to attemptToResumeMsgFromWx(), which apps call once their subscribers are ready (binding with the launch Want here would deliver a cold-start message before Dart listens, and again on attemptToResumeMsgFromWx). - registerApp re-binds on repeated calls instead of returning early. - attemptToResumeMsgFromWx now completes its MethodResult; previously `await attemptToResumeMsgFromWx()` never returned on HarmonyOS. Fixes #773 Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01F7jis66xcRRD5gTkwH1uLe --- .../ets/components/plugin/FluwxPlugin.ets | 3 +- .../plugin/handlers/WXAPiHandler.ets | 35 ++++++++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/_shared/ohos/src/main/ets/components/plugin/FluwxPlugin.ets b/packages/_shared/ohos/src/main/ets/components/plugin/FluwxPlugin.ets index a7996ad7..74bddda1 100644 --- a/packages/_shared/ohos/src/main/ets/components/plugin/FluwxPlugin.ets +++ b/packages/_shared/ohos/src/main/ets/components/plugin/FluwxPlugin.ets @@ -74,7 +74,7 @@ export default class FluwxPlugin implements FlutterPlugin, MethodCallHandler, Ab WXAPiHandler.checkWeChatInstallation(result); break; case "registerApp": - WXAPiHandler.registerApp(call, result); + WXAPiHandler.registerApp(call, result, this); break; case "sendAuth": this.authHandler?.sendAuth(call, result); @@ -262,6 +262,7 @@ export default class FluwxPlugin implements FlutterPlugin, MethodCallHandler, Ab attemptToResumeMsgFromWx(result: MethodResult) { WXAPiHandler.wxApi?.handleWant(this.binding?.getAbility().launchWant, this) + result.success(null) } async launchMiniProgram(call: MethodCall, result: MethodResult) { diff --git a/packages/_shared/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets b/packages/_shared/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets index ce351205..f24fb771 100644 --- a/packages/_shared/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets +++ b/packages/_shared/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets @@ -1,6 +1,6 @@ import * as wechatOpenSDK from "@tencent/wechat_open_sdk" import { MethodCall, MethodResult } from '@ohos/flutter_ohos' -import { bundleManager, common } from '@kit.AbilityKit' +import { bundleManager, common, Want } from '@kit.AbilityKit' export class WXAPiHandler { static wxApi: wechatOpenSDK.WXApi | null = null @@ -20,22 +20,33 @@ export class WXAPiHandler { WXAPiHandler.context = context } - static registerApp(call: MethodCall, result: MethodResult) { - if (WXAPiHandler.wxApi != null) { - result.success(true) - return + static registerApp(call: MethodCall, result: MethodResult, eventHandler: wechatOpenSDK.WXApiEventHandler) { + if (WXAPiHandler.wxApi == null) { + const appId: string | null = call.argument("appId") + if (!appId) { + result.error("invalid app id", "are you sure your app id is correct ?", appId) + return + } + WXAPiHandler.registerWxAPIInternal(appId) } - const appId: string | null = call.argument("appId") - if (!appId) { - result.error("invalid app id", "are you sure your app id is correct ?", appId) - return - } - - WXAPiHandler.registerWxAPIInternal(appId) + WXAPiHandler.bindEventHandler(eventHandler) result.success(WXAPiHandler.registered) } + // The SDK dispatches every response to the handler it received in the most recent handleWant() call, + // and handleWant() is the only way to hand it one. Responses coming back through the openLink channel + // (current WeChat versions) never go through onNewWant, so until something calls handleWant() the + // handler is null and the SDK drops them silently (`this.eventHandler?.onResp(...)`). That is what + // made the first auth / pay after every cold start time out (#773). + // + // An empty Want carries no WeChat payload, so this only binds the handler: nothing is dispatched and the + // launch Want is left for attemptToResumeMsgFromWx(), which apps call once their subscribers are ready. + private static bindEventHandler(eventHandler: wechatOpenSDK.WXApiEventHandler) { + const noPayload: Want = {} + WXAPiHandler.wxApi?.handleWant(noPayload, eventHandler) + } + static checkWeChatInstallation(result: MethodResult) { const isInstalled = bundleManager.canOpenLink("weixin://") || WXAPiHandler.wxApi?.isWXAppInstalled() === true; result.success(isInstalled);