From cc39d537fc47517b69549c92257c779507b94083 Mon Sep 17 00:00:00 2001 From: kaes1a Date: Fri, 16 Oct 2026 15:45:10 +0800 Subject: [PATCH] fix(ohos): align fluwx_no_pay HAR module name with Dart package name The ohos module of fluwx_no_pay was a symlink to ../_shared/ohos, whose HAR package/module name is "fluwx". The Flutter-OHOS toolchain generates plugin imports from the Dart package name (import ... from 'fluwx_no_pay'), so ohpm fails with '00604006 Inconsistent Dep Names' when building apps that depend on the published fluwx_no_pay package. Replace the symlink with a real copy of the shared ohos module and rename the HAR package/module name to "fluwx_no_pay". Closes #778 --- packages/fluwx_no_pay/ohos | 1 - packages/fluwx_no_pay/ohos/.gitignore | 9 + .../fluwx_no_pay/ohos/build-profile.json5 | 10 + packages/fluwx_no_pay/ohos/hvigorfile.ts | 2 + packages/fluwx_no_pay/ohos/index.ets | 17 + packages/fluwx_no_pay/ohos/oh-package.json5 | 12 + .../ets/components/plugin/FluwxPlugin.ets | 300 ++++++++++++++++++ .../plugin/handlers/FluwxAuthHandler.ets | 88 +++++ .../plugin/handlers/FluwxShareHandler.ets | 241 ++++++++++++++ .../plugin/handlers/WXAPiHandler.ets | 76 +++++ .../fluwx_no_pay/ohos/src/main/module.json5 | 10 + 11 files changed, 765 insertions(+), 1 deletion(-) delete mode 120000 packages/fluwx_no_pay/ohos create mode 100644 packages/fluwx_no_pay/ohos/.gitignore create mode 100644 packages/fluwx_no_pay/ohos/build-profile.json5 create mode 100644 packages/fluwx_no_pay/ohos/hvigorfile.ts create mode 100644 packages/fluwx_no_pay/ohos/index.ets create mode 100644 packages/fluwx_no_pay/ohos/oh-package.json5 create mode 100644 packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/FluwxPlugin.ets create mode 100644 packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxAuthHandler.ets create mode 100644 packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxShareHandler.ets create mode 100644 packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets create mode 100644 packages/fluwx_no_pay/ohos/src/main/module.json5 diff --git a/packages/fluwx_no_pay/ohos b/packages/fluwx_no_pay/ohos deleted file mode 120000 index 74fecdfa..00000000 --- a/packages/fluwx_no_pay/ohos +++ /dev/null @@ -1 +0,0 @@ -../_shared/ohos \ No newline at end of file diff --git a/packages/fluwx_no_pay/ohos/.gitignore b/packages/fluwx_no_pay/ohos/.gitignore new file mode 100644 index 00000000..161bdcda --- /dev/null +++ b/packages/fluwx_no_pay/ohos/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.cxx diff --git a/packages/fluwx_no_pay/ohos/build-profile.json5 b/packages/fluwx_no_pay/ohos/build-profile.json5 new file mode 100644 index 00000000..79961f96 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/build-profile.json5 @@ -0,0 +1,10 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "targets": [ + { + "name": "default" + } + ] +} diff --git a/packages/fluwx_no_pay/ohos/hvigorfile.ts b/packages/fluwx_no_pay/ohos/hvigorfile.ts new file mode 100644 index 00000000..47e6e1f8 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/hvigorfile.ts @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +export { harTasks } from '@ohos/hvigor-ohos-plugin'; \ No newline at end of file diff --git a/packages/fluwx_no_pay/ohos/index.ets b/packages/fluwx_no_pay/ohos/index.ets new file mode 100644 index 00000000..d6659ad4 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/index.ets @@ -0,0 +1,17 @@ +/* +* Copyright (c) 2023 Hunan OpenValley Digital Industry Development Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import FluwxPlugin from './src/main/ets/components/plugin/FluwxPlugin'; +export default FluwxPlugin; diff --git a/packages/fluwx_no_pay/ohos/oh-package.json5 b/packages/fluwx_no_pay/ohos/oh-package.json5 new file mode 100644 index 00000000..5631e613 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/oh-package.json5 @@ -0,0 +1,12 @@ +{ + "name": "fluwx_no_pay", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": { + "@ohos/flutter_ohos": "file:./har/flutter.har", + "@tencent/wechat_open_sdk": "1.0.19" + } +} diff --git a/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/FluwxPlugin.ets b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/FluwxPlugin.ets new file mode 100644 index 00000000..74bddda1 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/FluwxPlugin.ets @@ -0,0 +1,300 @@ +import { + AbilityAware, + AbilityPluginBinding, + FlutterPlugin, + FlutterPluginBinding, + MethodCall, + MethodCallHandler, + MethodChannel, + MethodResult, + NewWantListener, +} from '@ohos/flutter_ohos'; +import * as wechatSDK from "@tencent/wechat_open_sdk" +import { FluwxAuthHandler } from './handlers/FluwxAuthHandler'; +import { AbilityConstant, common, Want } from '@kit.AbilityKit'; +import { WXAPiHandler } from './handlers/WXAPiHandler'; +import { FluwxShareHandler } from './handlers/FluwxShareHandler'; + +const MESSAGE_CHANNEL_NAME = "com.jarvanmo/fluwx" +const KEY_ERR_STR = "errStr" +const KEY_ERR_CODE = "errCode" +const KEY_OPEN_ID = "openId" +const KEY_TYPE = "type" + +/** FluwxPlugin **/ +export default class FluwxPlugin implements FlutterPlugin, MethodCallHandler, AbilityAware, NewWantListener, wechatSDK.WXApiEventHandler { + private channel: MethodChannel | null = null; + private appContext: common.Context | null = null; + private uiContext: common.UIAbilityContext | null = null; + private binding: AbilityPluginBinding | null = null + private authHandler: FluwxAuthHandler | null = null; + private shareHandler: FluwxShareHandler | null = null; + private extMsg: string | null = null; + + getUniqueClassName(): string { + return "FluwxPlugin" + } + + onAttachedToEngine(binding: FlutterPluginBinding): void { + this.channel = new MethodChannel(binding.getBinaryMessenger(), MESSAGE_CHANNEL_NAME); + this.channel.setMethodCallHandler(this) + this.appContext = binding.getApplicationContext(); + this.authHandler = new FluwxAuthHandler(this.channel); + this.shareHandler = new FluwxShareHandler(); + } + + onDetachedFromEngine(binding: FlutterPluginBinding): void { + this.channel = null; + this.appContext = null; + this.authHandler = null; + this.shareHandler = null; + } + + onAttachedToAbility(binding: AbilityPluginBinding): void { + this.binding = binding + this.uiContext = binding.getAbility().context; + WXAPiHandler.setContext(this.uiContext); + binding.addOnNewWantListener(this) + } + + onDetachedFromAbility(): void { + this.binding?.removeOnNewWantListener(this) + this.binding = null + this.uiContext = null; + } + + onMethodCall(call: MethodCall, result: MethodResult): void { + if (call.method.startsWith("share")) { + this.shareHandler?.share(call, result); + return; + } + + switch (call.method) { + case "isWeChatInstalled": + WXAPiHandler.checkWeChatInstallation(result); + break; + case "registerApp": + WXAPiHandler.registerApp(call, result, this); + break; + case "sendAuth": + this.authHandler?.sendAuth(call, result); + break; + case "authByQRCode": + this.authHandler?.authByQRCode(call, result); + break; + case "stopAuthByQRCode": + this.authHandler?.stopAuthByQRCode(result); + break; + case "payWithFluwx": + this.handlePay(call, result); + break; + case "payWithHongKongWallet": + // TODO + result.notImplemented(); + break; + case "launchMiniProgram": + this.launchMiniProgram(call, result); + break; + case "subscribeMsg": + // TODO + result.notImplemented(); + break; + case "autoDeduct": + // TODO + result.notImplemented(); + break; + case "autoDeductV2": + // TODO + result.notImplemented(); + break; + case "openWXApp": + result.success(WXAPiHandler.wxApi?.openWechat(this.uiContext)); + break; + case "getExtMsg": + result.success(this.extMsg); + this.extMsg = null; + break; + case "openWeChatCustomerServiceChat": + this.openWeChatCustomerServiceChat(call, result); + break; + case "checkSupportOpenBusinessView": + WXAPiHandler.checkSupportOpenBusinessView(result); + break; + case "openBusinessView": + this.openBusinessView(call, result); + break; + case "openWeChatInvoice": + // TODO + result.notImplemented(); + break; + case "openUrl": + // TODO + result.notImplemented(); + break; + case "openRankList": + // TODO + result.notImplemented(); + break; + case "attemptToResumeMsgFromWx": + this.attemptToResumeMsgFromWx(result); + break; + case "selfCheck": + result.success(null) + break; + default: + result.notImplemented(); + } + } + + onNewWant(want: Want, launchParams: AbilityConstant.LaunchParam): void { + WXAPiHandler.wxApi?.handleWant(want, this); + } + + // 微信回调 start + + onReq = (req: wechatSDK.BaseReq): void => { + if (req instanceof wechatSDK.LaunchFromWXReq) { + const _result: Map = new Map(); + _result.set("extMsg", req.message?.messageExt); + _result.set("messageAction", req.message?.messageAction); + _result.set("lang", req.lang); + _result.set("country", req.country); + this.channel?.invokeMethod("onWXLaunchFromWX", _result); + } + } + + onResp = (resp: wechatSDK.BaseResp): void => { + if (resp instanceof wechatSDK.SendAuthResp) { + this.onAuthResponse(resp); + return; + } + + if (resp instanceof wechatSDK.SendMessageToWXResp) { + this.onSendMessageToWXResp(resp); + return; + } + + if (resp instanceof wechatSDK.PayResp) { + this.onPayResp(resp); + return; + } + + if (resp instanceof wechatSDK.LaunchMiniProgramResp) { + this.onLaunchMiniProgramResp(resp); + return; + } + } + + // 微信回调 end + + onAuthResponse(resp: wechatSDK.SendAuthResp) { + const result: Map = new Map(); + result.set(KEY_ERR_CODE, resp.errCode); + result.set(KEY_ERR_STR, resp.errStr); + result.set("code", resp.code); + result.set("state", resp.state); + result.set("lang", resp.lang); + result.set("country", resp.country); + result.set(KEY_OPEN_ID, resp.openId); + result.set("url", resp.url); + result.set(KEY_TYPE, resp.type); + + this.channel?.invokeMethod("onAuthResponse", result); + } + + onSendMessageToWXResp(resp: wechatSDK.SendMessageToWXResp) { + const _result: Map = new Map(); + _result.set(KEY_ERR_CODE, resp.errCode); + _result.set(KEY_ERR_STR, resp.errStr); + _result.set(KEY_TYPE, resp.type); + _result.set(KEY_OPEN_ID, resp.openId); + + this.channel?.invokeMethod("onShareResponse", _result); + } + + onPayResp(resp: wechatSDK.PayResp) { + const _result: Map = new Map(); + _result.set(KEY_ERR_CODE, resp.errCode); + _result.set(KEY_ERR_STR, resp.errStr); + _result.set(KEY_TYPE, resp.type); + _result.set("prepayId", resp.prepayId); + _result.set("returnKey", resp.returnKey); + _result.set("extData", resp.extData); + + this.channel?.invokeMethod("onPayResponse", _result); + } + + onLaunchMiniProgramResp(resp: wechatSDK.LaunchMiniProgramResp) { + const _result: Map = new Map(); + _result.set(KEY_ERR_CODE, resp.errCode); + _result.set(KEY_ERR_STR, resp.errStr); + _result.set(KEY_TYPE, resp.type); + _result.set(KEY_OPEN_ID, resp.openId); + + if (resp.extMsg) { + _result.set("extMsg", resp.extMsg); + } + + this.channel?.invokeMethod("onLaunchMiniProgramResponse", _result); + } + + async handlePay(call: MethodCall, result: MethodResult) { + if (!WXAPiHandler.wxApi) { + result.error("Unassigned WxApi", "please config wxapi first", null); + return; + } + + const request = new wechatSDK.PayReq(); + request.appId = call.argument("appId"); + request.partnerId = call.argument("partnerId"); + request.prepayId = call.argument("prepayId"); + request.packageValue = call.argument("packageValue"); + request.nonceStr = call.argument("nonceStr"); + request.timeStamp = call.argument("timeStamp").toString(); + request.sign = call.argument("sign"); + request.signType = call.argument("signType"); + request.extData = call.argument("extData"); + + const done = await WXAPiHandler.wxApi?.sendReq(this.uiContext, request); + + result.success(done); + } + + attemptToResumeMsgFromWx(result: MethodResult) { + WXAPiHandler.wxApi?.handleWant(this.binding?.getAbility().launchWant, this) + result.success(null) + } + + async launchMiniProgram(call: MethodCall, result: MethodResult) { + const request = new wechatSDK.LaunchMiniProgramReq(); + request.userName = call.argument("userName"); + request.path = call.argument("path"); + // sdk 内当前没 type 常量, 直接使用传入的参数 + request.miniprogramType = call.argument("miniProgramType") ?? 0; + + const done = await WXAPiHandler.wxApi?.sendReq(this.uiContext, request); + + result.success(done); + } + + async openBusinessView(call: MethodCall, result: MethodResult) { + const request = new wechatSDK.OpenBusinessViewReq(); + request.businessType = call.argument("businessType"); + request.query = call.argument("query"); + request.extInfo = `{"miniProgramType": 0}`; + + const done = await WXAPiHandler.wxApi?.sendReq(this.uiContext, request); + + result.success(done); + } + + async openWeChatCustomerServiceChat(call: MethodCall, result: MethodResult) { + const request = new wechatSDK.OpenCustomerServiceChatReq(); + request.corpId = call.argument("corpId") ?? ""; + request.url = call.argument("url") ?? ""; + + const done = await WXAPiHandler.wxApi?.sendReq(this.uiContext, request); + + result.success(done); + } +} diff --git a/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxAuthHandler.ets b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxAuthHandler.ets new file mode 100644 index 00000000..0d863638 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxAuthHandler.ets @@ -0,0 +1,88 @@ +import { MethodCall, MethodChannel, MethodResult } from "@ohos/flutter_ohos"; +import { DiffDevOAuthFactory, IDiffDevOAuth, OAuthCallback, OAuthErrCode, SendAuthReq } from "@tencent/wechat_open_sdk"; +import { WXAPiHandler } from "./WXAPiHandler"; +import { util } from "@kit.ArkTS"; + +export class FluwxAuthHandler implements OAuthCallback { + private channel: MethodChannel; + private diffDevOauth: IDiffDevOAuth | null = null; + + constructor(channel: MethodChannel) { + this.channel = channel; + } + + onGotQRCode = (base64JpegImageBuffer: string) => { + const base64Codec = new util.Base64Helper() + const bytes = base64Codec.decodeSync(base64JpegImageBuffer) + + this.channel.invokeMethod("onAuthGotQRCode", { + "errCode": 0, + "qrCode": bytes + }) + } + onQRCodeScanned = () => { + this.channel.invokeMethod("onQRCodeScanned", { + "errCode": 0 + }) + } + onAuthFinish = (authCode: string) => { + this.channel.invokeMethod("onAuthByQRCodeFinished", { + "authCode": authCode, + "errCode": 0 + }) + } + onAuthError = (errCode: OAuthErrCode, errMsg: string) => { + this.channel.invokeMethod("onAuthByQRCodeFinished", { + "errCode": errCode, + "errStr": errMsg + }) + } + + getDiffDevOauth(): IDiffDevOAuth { + if (this.diffDevOauth) { + this.diffDevOauth.stopOAuth(); + this.diffDevOauth = null; + } + this.diffDevOauth = DiffDevOAuthFactory.getDiffDevOAuth()!; + return this.diffDevOauth; + } + + async sendAuth(call: MethodCall, result: MethodResult) { + const req = new SendAuthReq(); + req.isOption1 = false; + req.scope = call.argument("scope"); + req.state = call.argument("state"); + const openid: string | null = call.argument("openid"); + if (openid) { + req.openId = openid; + } + req.nonAutomatic = call.argument("nonAutomatic") ?? false; + + const done = await WXAPiHandler.wxApi?.sendReq(WXAPiHandler.uiContext, req); + + result.success(done ?? false); + } + + authByQRCode(call: MethodCall, result: MethodResult) { + const appId: string = call.argument("appId") ?? ""; + const scope: string = call.argument("scope") ?? ""; + const nonceStr: string = call.argument("nonceStr") ?? ""; + const timeStamp: string = call.argument("timeStamp") ?? ""; + const signature: string = call.argument("signature") ?? ""; + + const qrCodeAuth = this.getDiffDevOauth(); + + result.success(qrCodeAuth.startOAuth( + appId, + scope, + nonceStr, + timeStamp, + signature, + this + )) + } + + stopAuthByQRCode(result: MethodResult) { + result.success(this.diffDevOauth?.stopOAuth()) + } +} \ No newline at end of file diff --git a/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxShareHandler.ets b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxShareHandler.ets new file mode 100644 index 00000000..515b735f --- /dev/null +++ b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/FluwxShareHandler.ets @@ -0,0 +1,241 @@ +import { Any, MethodCall, MethodResult } from "@ohos/flutter_ohos" +import { buffer } from "@kit.ArkTS" +import { fileUri, fileIo as fs } from "@kit.CoreFileKit" +import * as wxopensdk from '@tencent/wechat_open_sdk'; +import { WXAPiHandler } from "./WXAPiHandler" + +export class FluwxShareHandler { + share(call: MethodCall, result: MethodResult) { + if (!WXAPiHandler.wxApi) { + result.error("Unassigned WxApi", "please config wxapi first", null); + return; + } + + switch (call.method) { + case "shareText": + this.shareText(call, result); + break; + case "shareMiniProgram": + this.shareMiniProgram(call, result); + break; + case "shareImage": + this.shareImage(call, result); + break; + case "shareMusic": + // TODO + result.notImplemented(); + break; + case "shareVideo": + this.shareVideo(call, result); + break; + case "shareWebPage": + this.shareWebPage(call, result); + break; + case "shareFile": + this.shareFile(call, result); + break; + default: + result.notImplemented(); + break; + } + } + + async shareText(call: MethodCall, result: MethodResult) { + const textObj = new wxopensdk.WXTextObject(); + textObj.text = call.argument("source"); + + const mediaMsg = new wxopensdk.WXMediaMessage(); + mediaMsg.mediaObject = textObj; + + const req = new wxopensdk.SendMessageToWXReq(); + this.setCommonArgs(call, req, mediaMsg); + req.message = mediaMsg; + + const done = await WXAPiHandler.wxApi?.sendReq(WXAPiHandler.uiContext, req); + + result.success(done) + } + + async shareImage(call: MethodCall, result: MethodResult) { + const map: Map = call.argument("source") ?? new Map(); + // const imageHash: string | null = call.argument("imgDataHash"); + const bytes: Uint8Array | null = map.get("uint8List"); + + const imageObj = new wxopensdk.WXImageObject(); + + if (bytes) { + const buff: buffer.Buffer = buffer.from(bytes.buffer); + imageObj.imageData = buff.toString("base64", 0, buff.length); + } else { + const localImagePath: string | null = map.get("localImagePath"); + if (localImagePath) { + imageObj.uri = localImagePath.startsWith("file://") ? localImagePath : fileUri.getUriFromPath(localImagePath) + } + } + + const mediaMsg = new wxopensdk.WXMediaMessage(); + mediaMsg.mediaObject = imageObj; + + const req = new wxopensdk.SendMessageToWXReq(); + this.setCommonArgs(call, req, mediaMsg); + req.message = mediaMsg; + + const done = await WXAPiHandler.wxApi?.sendReq(WXAPiHandler.uiContext, req); + result.success(done); + } + + async shareWebPage(call: MethodCall, result: MethodResult) { + const webpageObject = new wxopensdk.WXWebpageObject() + webpageObject.webpageUrl = call.argument("webPage") + + const mediaMessage = new wxopensdk.WXMediaMessage() + mediaMessage.mediaObject = webpageObject + mediaMessage.title = call.argument("title") + mediaMessage.description = call.argument("description") + + const thumbData: Uint8Array | null = call.argument("thumbData"); + if (thumbData) { + mediaMessage.thumbData = thumbData; + } + + const req = new wxopensdk.SendMessageToWXReq() + this.setCommonArgs(call, req, mediaMessage) + req.message = mediaMessage + + const done = await WXAPiHandler.wxApi?.sendReq(WXAPiHandler.uiContext, req); + + result.success(done) + } + + async shareFile(call: MethodCall, result: MethodResult) { + const source: Map = call.argument("source") ?? new Map(); + const schemaIndex: number = source.get("schema") + let filePath: string = "" + + // check schema is file or binary + if (schemaIndex < 2) { + result.error("ARG", "currently only file or binary schema is supported on ohos", null); + return; + } + + // case schema is file + if(schemaIndex == 2) { + filePath = source.get("source") + if (filePath.startsWith("file://")) { + filePath = filePath; + } else { + filePath = fileUri.getUriFromPath(filePath); + } + } else { + // case schema is binary, write to temp file first + const bytes: Uint8Array = source.get("source"); + const suffix: string = source.get("suffix") ?? ".tmp"; + const fileName = `share_temp_${new Date().getTime()}${suffix}`; + const tempFilePath = `${WXAPiHandler.uiContext?.tempDir}/${fileName}`; + const tempFile = fs.openSync(tempFilePath, fs.OpenMode.READ_WRITE || fs.OpenMode.CREATE); + await fs.write(tempFile.fd, bytes.buffer); + await fs.close(tempFile.fd); + filePath = fileUri.getUriFromPath(tempFilePath); + } + + const fileObject = new wxopensdk.WXFileObject() + fileObject.fileUri = filePath + + const mediaMessage = new wxopensdk.WXMediaMessage() + mediaMessage.mediaObject = fileObject + mediaMessage.title = call.argument("title") || "" + mediaMessage.description = call.argument("description") || "" + + const req = new wxopensdk.SendMessageToWXReq() + this.setCommonArgs(call, req, mediaMessage) + req.message = mediaMessage + + const done = await WXAPiHandler.wxApi?.sendReq(WXAPiHandler.uiContext, req); + + result.success(done) + } + + async shareMiniProgram(call: MethodCall, result: MethodResult) { + const miniProgramObject = new wxopensdk.WXMiniProgramObject() + miniProgramObject.userName = call.argument("userName") + miniProgramObject.path = call.argument("path") + + let miniProgramType = wxopensdk.WXMiniProgramType.RELEASE + + let miniProgramTypeInt: number = call.argument("miniProgramType") + if (miniProgramTypeInt === 1) { + miniProgramType = wxopensdk.WXMiniProgramType.TEST + } else if (miniProgramTypeInt === 2) { + miniProgramType = wxopensdk.WXMiniProgramType.PREVIEW + } + + miniProgramObject.miniprogramType = miniProgramType + + const mediaMessage = new wxopensdk.WXMediaMessage() + mediaMessage.mediaObject = miniProgramObject + mediaMessage.title = call.argument("title") + mediaMessage.description = call.argument("description") + + const thumbData: Uint8Array | null = call.argument("thumbData"); + if (thumbData) { + mediaMessage.thumbData = thumbData; + } + + const req = new wxopensdk.SendMessageToWXReq() + this.setCommonArgs(call, req, mediaMessage) + req.message = mediaMessage + + const done = await WXAPiHandler.wxApi?.sendReq(WXAPiHandler.uiContext, req); + + result.success(done) + } + + async shareVideo(call: MethodCall, result: MethodResult) { + const videoObject = new wxopensdk.WXVideoObject() + const videoUrl: string | undefined = call.argument("videoUrl"); + const videoLowBandUrl: string | undefined = call.argument("videoLowBandUrl"); + + if (videoUrl) { + videoObject.videoUrl = videoUrl; + } else { + videoObject.videoLowBandUrl = videoLowBandUrl; + } + + const mediaMessage = new wxopensdk.WXMediaMessage() + mediaMessage.mediaObject = videoObject + mediaMessage.title = call.argument("title") || "" + mediaMessage.description = call.argument("description") || "" + + const req = new wxopensdk.SendMessageToWXReq() + this.setCommonArgs(call, req, mediaMessage) + req.message = mediaMessage + const done = await WXAPiHandler.wxApi?.sendReq(WXAPiHandler.uiContext, req); + result.success(done) + } + + setCommonArgs(call: MethodCall, req: wxopensdk.SendMessageToWXReq, msg: wxopensdk.WXMediaMessage) { + const thumbData: Uint8Array | undefined = call.argument("thumbData"); + const messageAction: string | undefined = call.argument("messageAction"); + + if (thumbData) { + msg.thumbData = thumbData; + } + + if (messageAction) { + msg.messageAction = messageAction; + } + + const sceneIndex: number = call.argument("scene") + switch (sceneIndex) { + case 0: + req.scene = wxopensdk.SendMessageToWXReq.WXSceneSession + break + case 1: + req.scene = wxopensdk.SendMessageToWXReq.WXSceneTimeline + break + default: + req.scene = wxopensdk.SendMessageToWXReq.WXSceneSession + break + } + } +} \ No newline at end of file diff --git a/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets new file mode 100644 index 00000000..f24fb771 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/src/main/ets/components/plugin/handlers/WXAPiHandler.ets @@ -0,0 +1,76 @@ +import * as wechatOpenSDK from "@tencent/wechat_open_sdk" +import { MethodCall, MethodResult } from '@ohos/flutter_ohos' +import { bundleManager, common, Want } from '@kit.AbilityKit' + +export class WXAPiHandler { + static wxApi: wechatOpenSDK.WXApi | null = null + private static registered: boolean = false + private static context: common.UIAbilityContext | null = null + + static get wxApiRegistered() { + return WXAPiHandler.registered + } + static get uiContext() { + return WXAPiHandler.context + } + + static coolBoot: boolean = false + + static setContext(context: common.UIAbilityContext) { + WXAPiHandler.context = context + } + + 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) + } + + 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); + } + + static checkSupportOpenBusinessView(result: MethodResult) { + if (!WXAPiHandler.wxApi) { + result.error("Unassigned WxApi", "please config wxapi first", null); + return; + } + + const isInstalled = bundleManager.canOpenLink("weixin://") || WXAPiHandler.wxApi?.isWXAppInstalled() === true; + if (!isInstalled) { + result.error("WeChat Not Installed", "Please install the WeChat first", null); + return; + } + + result.success(true); + } + + + private static registerWxAPIInternal(appId: string) { + let api = wechatOpenSDK.WXAPIFactory.createWXAPI(appId) + WXAPiHandler.registered = true + WXAPiHandler.wxApi = api + } +} \ No newline at end of file diff --git a/packages/fluwx_no_pay/ohos/src/main/module.json5 b/packages/fluwx_no_pay/ohos/src/main/module.json5 new file mode 100644 index 00000000..b30a73e1 --- /dev/null +++ b/packages/fluwx_no_pay/ohos/src/main/module.json5 @@ -0,0 +1,10 @@ +{ + "module": { + "name": "fluwx_no_pay", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ] + } +}