feat:转账插件
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@tencent/wechat_open_sdk": "1.0.15"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import { RequestMerchantTransfer, RequestMerchantTransferGeneralCallbackResult, RequestMerchantTransferOptions } from '../interface.uts'
|
||||
import {
|
||||
handleWechatMerchantTransferWant,
|
||||
requestWechatMerchantTransfer,
|
||||
WechatMerchantTransferNativeResult
|
||||
} from './wechatMerchantTransfer.ets'
|
||||
import {
|
||||
REQUEST_MERCHANT_TRANSFER_APP_ID_REQUIRED,
|
||||
REQUEST_MERCHANT_TRANSFER_BUSINESS_FAILED,
|
||||
REQUEST_MERCHANT_TRANSFER_CANCEL,
|
||||
REQUEST_MERCHANT_TRANSFER_MCH_ID_REQUIRED,
|
||||
REQUEST_MERCHANT_TRANSFER_OK,
|
||||
REQUEST_MERCHANT_TRANSFER_OPEN_SDK_ERROR,
|
||||
REQUEST_MERCHANT_TRANSFER_PACKAGE_REQUIRED,
|
||||
REQUEST_MERCHANT_TRANSFER_PARSE_RESPONSE_ERROR,
|
||||
REQUEST_MERCHANT_TRANSFER_WECHAT_NOT_INSTALLED,
|
||||
REQUEST_MERCHANT_TRANSFER_WECHAT_VERSION_LOW
|
||||
} from '../unierror.uts'
|
||||
|
||||
let isWechatMerchantTransferHandlerRegistered = false
|
||||
|
||||
function ensureWechatMerchantTransferHandlerRegistered() : void {
|
||||
if (isWechatMerchantTransferHandlerRegistered) {
|
||||
return
|
||||
}
|
||||
isWechatMerchantTransferHandlerRegistered = true
|
||||
UTSHarmony.onAppAbilityCreate((want, _launchParam) => {
|
||||
handleWechatMerchantTransferWant(want)
|
||||
})
|
||||
UTSHarmony.onAppAbilityNewWant((want, _launchParam) => {
|
||||
handleWechatMerchantTransferWant(want)
|
||||
})
|
||||
}
|
||||
|
||||
function invokeCallback(options : RequestMerchantTransferOptions, errMsg : string, isSuccess : boolean) : void {
|
||||
const result : RequestMerchantTransferGeneralCallbackResult = {
|
||||
errMsg: errMsg
|
||||
}
|
||||
if (isSuccess) {
|
||||
options.success?.(result)
|
||||
} else {
|
||||
options.fail?.(result)
|
||||
}
|
||||
options.complete?.(result)
|
||||
}
|
||||
|
||||
function isEmptyString(value : string | null) : boolean {
|
||||
return value == null || value.length == 0
|
||||
}
|
||||
|
||||
function appendQueryParam(query : string, key : string, value : string) : string {
|
||||
const param = key + '=' + encodeURIComponent(value)
|
||||
if (query.length > 0) {
|
||||
return query + '&' + param
|
||||
}
|
||||
return param
|
||||
}
|
||||
|
||||
function getValidateErrorMsg(options : RequestMerchantTransferOptions) : string {
|
||||
if (isEmptyString(options.mchId)) {
|
||||
return REQUEST_MERCHANT_TRANSFER_MCH_ID_REQUIRED.errMsg
|
||||
}
|
||||
if (isEmptyString(options.package)) {
|
||||
return REQUEST_MERCHANT_TRANSFER_PACKAGE_REQUIRED.errMsg
|
||||
}
|
||||
if (isEmptyString(options.appId)) {
|
||||
return REQUEST_MERCHANT_TRANSFER_APP_ID_REQUIRED.errMsg
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
function buildRequestMerchantTransferQuery(options : RequestMerchantTransferOptions, appId : string) : string {
|
||||
let query = ''
|
||||
// 微信官方文档上只有下方3个参数,没有 openId、subAppId、subMchId
|
||||
// 相关文档:
|
||||
// 用户确认收款:https://pay.weixin.qq.com/doc/v3/merchant/4019670774
|
||||
// 免确认收款授权:https://pay.weixin.qq.com/doc/v3/merchant/4020320137
|
||||
query = appendQueryParam(query, 'mchId', options.mchId)
|
||||
query = appendQueryParam(query, 'package', options.package)
|
||||
query = appendQueryParam(query, 'appId', appId)
|
||||
return query
|
||||
}
|
||||
|
||||
function handleNativeResult(options : RequestMerchantTransferOptions, nativeResult : WechatMerchantTransferNativeResult) : void {
|
||||
if (nativeResult.result == 'success') {
|
||||
invokeCallback(options, REQUEST_MERCHANT_TRANSFER_OK, true)
|
||||
return
|
||||
}
|
||||
|
||||
let errMsg = REQUEST_MERCHANT_TRANSFER_BUSINESS_FAILED.errMsg
|
||||
if (nativeResult.result == 'cancel') {
|
||||
errMsg = REQUEST_MERCHANT_TRANSFER_CANCEL.errMsg
|
||||
} else if (nativeResult.result == 'wechat_not_installed') {
|
||||
errMsg = REQUEST_MERCHANT_TRANSFER_WECHAT_NOT_INSTALLED.errMsg
|
||||
} else if (nativeResult.result == 'wechat_version_low') {
|
||||
errMsg = REQUEST_MERCHANT_TRANSFER_WECHAT_VERSION_LOW.errMsg
|
||||
} else if (nativeResult.result == 'parse_response_error') {
|
||||
errMsg = REQUEST_MERCHANT_TRANSFER_PARSE_RESPONSE_ERROR.errMsg
|
||||
} else if (nativeResult.result == 'open_sdk_error' || nativeResult.result == 'timeout' || nativeResult.result == 'request_interrupted') {
|
||||
errMsg = REQUEST_MERCHANT_TRANSFER_OPEN_SDK_ERROR.errMsg
|
||||
}
|
||||
invokeCallback(options, errMsg, false)
|
||||
}
|
||||
|
||||
export const requestMerchantTransfer : RequestMerchantTransfer = function (options : RequestMerchantTransferOptions) {
|
||||
const validateErrorMsg = getValidateErrorMsg(options)
|
||||
if (validateErrorMsg.length > 0) {
|
||||
invokeCallback(options, validateErrorMsg, false)
|
||||
return
|
||||
}
|
||||
|
||||
ensureWechatMerchantTransferHandlerRegistered()
|
||||
const appId : string = options.appId ?? ''
|
||||
const query = buildRequestMerchantTransferQuery(options, appId)
|
||||
requestWechatMerchantTransfer(appId, query).then((nativeResult : WechatMerchantTransferNativeResult) => {
|
||||
handleNativeResult(options, nativeResult)
|
||||
}).catch((_error : Error) => {
|
||||
invokeCallback(options, REQUEST_MERCHANT_TRANSFER_OPEN_SDK_ERROR.errMsg, false)
|
||||
})
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
import { common, Want } from '@kit.AbilityKit';
|
||||
import * as wxopensdk from '@tencent/wechat_open_sdk';
|
||||
|
||||
export class WechatMerchantTransferNativeResult {
|
||||
result: string = '';
|
||||
errMsg: string = '';
|
||||
extMsg: string = '';
|
||||
|
||||
constructor(result: string, errMsg: string, extMsg: string) {
|
||||
this.result = result;
|
||||
this.errMsg = errMsg;
|
||||
this.extMsg = extMsg;
|
||||
}
|
||||
}
|
||||
|
||||
const MERCHANT_TRANSFER_BUSINESS_TYPE: string = 'requestMerchantTransfer';
|
||||
const REQUEST_TIMEOUT_MS: number = 120000;
|
||||
|
||||
let currentAppId: string = '';
|
||||
let currentWxApi: wxopensdk.WXApi | null = null;
|
||||
let pendingResolve: ((result: WechatMerchantTransferNativeResult) => void) | null = null;
|
||||
let timeoutId: number = -1;
|
||||
|
||||
class MerchantTransferRespPayload {
|
||||
result: string | null = null;
|
||||
}
|
||||
|
||||
function buildResult(result: string, errMsg: string, extMsg: string): WechatMerchantTransferNativeResult {
|
||||
return new WechatMerchantTransferNativeResult(result, errMsg, extMsg);
|
||||
}
|
||||
|
||||
function getWxApi(appId: string): wxopensdk.WXApi {
|
||||
let wxApi = currentWxApi;
|
||||
if (wxApi == null || currentAppId != appId) {
|
||||
currentAppId = appId;
|
||||
wxApi = wxopensdk.WXAPIFactory.createWXAPI(appId);
|
||||
currentWxApi = wxApi;
|
||||
}
|
||||
return wxApi;
|
||||
}
|
||||
|
||||
function clearPendingTimeout(): void {
|
||||
if (timeoutId != -1) {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
function finishPending(result: WechatMerchantTransferNativeResult): void {
|
||||
const resolve = pendingResolve;
|
||||
pendingResolve = null;
|
||||
clearPendingTimeout();
|
||||
if (resolve != null) {
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
function parseMerchantTransferResp(extMsg: string): WechatMerchantTransferNativeResult {
|
||||
if (extMsg.length == 0) {
|
||||
return buildResult('parse_response_error', 'parse response failed', extMsg);
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = JSON.parse(extMsg) as MerchantTransferRespPayload;
|
||||
const result: string = payload.result ?? '';
|
||||
|
||||
if (result == 'success') {
|
||||
return buildResult('success', '', extMsg);
|
||||
}
|
||||
if (result == 'fail') {
|
||||
return buildResult('fail', 'business failed', extMsg);
|
||||
}
|
||||
if (result == 'cancel') {
|
||||
return buildResult('cancel', 'business canceled', extMsg);
|
||||
}
|
||||
return buildResult('business_failed', 'unknown business result', extMsg);
|
||||
} catch (_error) {
|
||||
return buildResult('parse_response_error', 'parse response failed', extMsg);
|
||||
}
|
||||
}
|
||||
|
||||
class WechatMerchantTransferEventHandler implements wxopensdk.WXApiEventHandler {
|
||||
onResp(resp: wxopensdk.BaseResp): void {
|
||||
if (resp instanceof wxopensdk.OpenBusinessViewResp) {
|
||||
if ("requestMerchantTransfer" === resp.businessType) {
|
||||
if (resp.errCode == wxopensdk.ErrCode.ERR_UNSUPPORTED) {
|
||||
finishPending(buildResult('wechat_version_low', resp.errStr ?? 'wechat version is too low', ''));
|
||||
return;
|
||||
}
|
||||
|
||||
const businessType: string = resp.businessType ?? '';
|
||||
if (businessType != MERCHANT_TRANSFER_BUSINESS_TYPE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const extMsg: string = resp.extMsg ?? '';
|
||||
if (resp.errCode == wxopensdk.ErrCode.ERR_USER_CANCEL && extMsg.length == 0) {
|
||||
finishPending(buildResult('cancel', resp.errStr ?? 'business canceled', ''));
|
||||
return;
|
||||
}
|
||||
finishPending(parseMerchantTransferResp(extMsg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onReq(_req: wxopensdk.BaseReq): void {
|
||||
}
|
||||
}
|
||||
|
||||
const wxEventHandler = new WechatMerchantTransferEventHandler();
|
||||
|
||||
export async function requestWechatMerchantTransfer(appId: string, query: string): Promise<WechatMerchantTransferNativeResult> {
|
||||
if (appId == '') {
|
||||
return buildResult('invalid_app_id', 'appId is empty', '');
|
||||
}
|
||||
if (query == '') {
|
||||
return buildResult('invalid_query', 'query is empty', '');
|
||||
}
|
||||
|
||||
const wxApi: wxopensdk.WXApi = getWxApi(appId);
|
||||
|
||||
if (!wxApi.isWXAppInstalled()) {
|
||||
return buildResult('wechat_not_installed', 'wechat is not installed', '');
|
||||
}
|
||||
|
||||
const req = new wxopensdk.OpenBusinessViewReq();
|
||||
req.businessType = MERCHANT_TRANSFER_BUSINESS_TYPE;
|
||||
req.query = query;
|
||||
|
||||
const context = getContext() as common.UIAbilityContext;
|
||||
const responsePromise = new Promise<WechatMerchantTransferNativeResult>((resolve) => {
|
||||
if (pendingResolve != null) {
|
||||
finishPending(buildResult('request_interrupted', 'another merchant transfer request started', ''));
|
||||
}
|
||||
|
||||
pendingResolve = resolve;
|
||||
timeoutId = setTimeout(() => {
|
||||
finishPending(buildResult('timeout', 'wait wechat response timeout', ''));
|
||||
}, REQUEST_TIMEOUT_MS);
|
||||
});
|
||||
|
||||
try {
|
||||
const sendResult: boolean = await wxApi.sendReq(context, req);
|
||||
if (!sendResult) {
|
||||
finishPending(buildResult('open_sdk_error', 'sendReq returned false', ''));
|
||||
}
|
||||
} catch (_error) {
|
||||
finishPending(buildResult('open_sdk_error', 'sendReq failed', ''));
|
||||
}
|
||||
|
||||
return responsePromise;
|
||||
}
|
||||
|
||||
export function handleWechatMerchantTransferWant(want: Want): void {
|
||||
const wxApi = currentWxApi;
|
||||
if (wxApi == null || currentAppId.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
wxApi.handleWant(want, wxEventHandler);
|
||||
}
|
||||
Reference in New Issue
Block a user