@react-native-ohos/react-native-wechat-lib
Version:
react native ohos react native wechat lib
500 lines (453 loc) • 13.2 kB
text/typescript
import { EventEmitter } from "events";
import { DeviceEventEmitter } from "react-native";
import WechatLib, {
LaunchMiniProgramMetadata,
PaymentLoad,
ShareFileMetadata,
ShareImageMetadata,
ShareMiniProgramMetadata,
ShareMusicMetadata,
ShareTextMetadata,
ShareVideoMetadata,
ShareWebpageMetadata,
SubscribeMessageMetadata,
} from "./specs/NativeRNWechatLibModule";
let isAppRegistered = false;
// Event emitter to dispatch request and response from WechatLib.
const emitter = new EventEmitter();
DeviceEventEmitter.addListener("WeChat_Resp", (resp) => {
emitter.emit(resp.type, resp);
});
DeviceEventEmitter.addListener("WeChat_Req", (resp) => {
emitter.emit(resp.type, resp);
});
type Callback = (error: any, result: any) => void;
function wrapRegisterApp(nativeFunc: ((...args: any[]) => void) | undefined) {
if (!nativeFunc) {
return undefined;
}
return (...args: any[]): Promise<boolean> => {
if (isAppRegistered) {
return Promise.resolve(true);
}
isAppRegistered = true; // 注册状态修改
return new Promise((resolve, reject) => {
nativeFunc.apply(null, [
...args,
(error: any, result: any) => {
if (!error) {
return resolve(result);
}
if (typeof error === "string") {
return reject(new Error(error));
}
reject(error);
},
] as [...any[], Callback]);
});
};
}
function wrapApi(nativeFunc: ((...args: any[]) => void) | undefined) {
if (!nativeFunc) {
return undefined;
}
return (...args: any[]): Promise<any> => {
if (!isAppRegistered) {
return Promise.reject(new Error("registerApp required."));
}
return new Promise((resolve, reject) => {
nativeFunc.apply(null, [
...args,
(error: any, result: any) => {
if (!error) {
return resolve(result);
}
if (typeof error === "string") {
return reject(new Error(error));
}
reject(error);
},
] as [...any[], Callback]);
});
};
}
/**
* `addListener` inherits from `events` module
* @method addListener
* @param {String} eventName - the event name
* @param {Function} trigger - the function when event is fired
*/
export const addListener = emitter.addListener.bind(emitter);
/**
* `once` inherits from `events` module
* @method once
* @param {String} eventName - the event name
* @param {Function} trigger - the function when event is fired
*/
export const once = emitter.once.bind(emitter);
/**
* `removeAllListeners` inherits from `events` module
* @method removeAllListeners
* @param {String} eventName - the event name
*/
export const removeAllListeners = emitter.removeAllListeners.bind(emitter);
/**
* @method registerApp
* @param {String} appid - the app id
* @return {Promise}
*/
export const registerApp = wrapRegisterApp(WechatLib.registerApp);
// /**
// * @method registerAppWithDescription
// * @param {String} appid - the app id
// * @param {String} appdesc - the app description
// * @return {Promise}
// */
// export const registerAppWithDescription = wrapRegisterApp(
// WechatLib.registerAppWithDescription,
// );
/**
* Return if the wechat app is installed in the device.
* @method isWXAppInstalled
* @return {Promise}
*/
export const isWXAppInstalled = wrapApi(WechatLib.isWXAppInstalled);
/**
* Return if the wechat application supports the api
* @method isWXAppSupportApi
* @return {Promise}
*/
export const isWXAppSupportApi = wrapApi(WechatLib.isWXAppSupportApi);
/**
* Get the wechat app installed url
* @method getWXAppInstallUrl
* @return {String} the wechat app installed url
*/
// export const getWXAppInstallUrl = wrapApi(WechatLib.getWXAppInstallUrl);
/**
* Get the wechat api version
* @method getApiVersion
* @return {String} the api version string
*/
export const getApiVersion = wrapApi(WechatLib.getApiVersion);
/**
* Open wechat app
* @method openWXApp
* @return {Promise}
*/
export const openWXApp = wrapApi(WechatLib.openWXApp);
// wrap the APIs
const nativeLaunchMiniProgram = wrapApi(WechatLib.launchMiniProgram);
const nativeShareText = wrapApi(WechatLib.shareText);
const nativeShareImage = wrapApi(WechatLib.shareImage);
const nativeShareLocalImage = wrapApi(WechatLib.shareLocalImage);
const nativeShareMusic = wrapApi(WechatLib.shareMusic);
const nativeShareVideo = wrapApi(WechatLib.shareVideo);
const nativeShareWebpage = wrapApi(WechatLib.shareWebpage);
const nativeShareMiniProgram = wrapApi(WechatLib.shareMiniProgram);
const nativeSubscribeMessage = wrapApi(WechatLib.subscribeMessage);
const nativeChooseInvoice = wrapApi(WechatLib.chooseInvoice);
const nativeShareFile = wrapApi(WechatLib.shareFile);
export const authByScan = wrapApi(WechatLib.authByScan);
const NormalRes = { errCode: 0, errStr: '' };
/**
* @method sendAuthRequest
* @param {Array} scopes - the scopes for authentication.
* @return {Promise}
*/
export function sendAuthRequest(scopes: string, state: string) {
return new Promise((resolve, reject) => {
const onSendAuthRes = (resp: any) => {
WechatLib.unregisterCallback("SendAuth.Resp");
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
};
WechatLib.registerCallback("SendAuth.Resp", onSendAuthRes);
WechatLib.sendAuthRequest(scopes, state, () => {});
});
}
/**
* Share text
* @method shareText
* @param {Object} data
*/
export function shareText(data: ShareTextMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
return new Promise(async (resolve, reject) => {
try {
await nativeShareText?.(data)
resolve(NormalRes);
} catch (error) {
reject({ errCode: -1, errStr: (error as Error).message })
}
});
}
/**
* Choose Invoice
* @method chooseInvoice
* @param {Object} data
*/
export function chooseInvoice(data = {}) {
return new Promise((resolve, reject) => {
nativeChooseInvoice?.(data);
emitter.once("WXChooseInvoiceResp.Resp", (resp) => {
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
});
});
}
/**
* Share File
* @method shareFile
* @param {Object} data
*/
export function shareFile(data: ShareFileMetadata) {
return new Promise((resolve, reject) => {
nativeShareFile?.(data);
emitter.once("SendMessageToWX.Resp", (resp) => {
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
});
});
}
/**
* Share image
* @method shareImage
* @param {Object} data
*/
export function shareImage(data: ShareImageMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
return new Promise(async (resolve, reject) => {
try {
await nativeShareImage?.(data);
resolve(NormalRes);
} catch (error) {
reject({ errCode: -1, errStr: (error as Error).message })
}
});
}
/**
* Share local image
* @method shareLocalImage
* @param {Object} data
*/
export function shareLocalImage(data: ShareImageMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
return new Promise(async (resolve, reject) => {
try {
await nativeShareLocalImage?.(data);
resolve(NormalRes);
} catch (error) {
reject({ errCode: -1, errStr: (error as Error).message })
}
});
}
/**
* Share music
* @method shareMusic
* @param {Object} data
*/
export function shareMusic(data: ShareMusicMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
return new Promise((resolve, reject) => {
nativeShareMusic?.(data);
emitter.once("SendMessageToWX.Resp", (resp) => {
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
});
});
}
/**
* Share video
* @method shareVideo
* @param {Object} data
*/
export function shareVideo(data: ShareVideoMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
return new Promise((resolve, reject) => {
nativeShareVideo?.(data);
emitter.once("SendMessageToWX.Resp", (resp) => {
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
});
});
}
/**
* Share webpage
* @method shareWebpage
* @param {Object} data
*/
export function shareWebpage(data: ShareWebpageMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
return new Promise((resolve, reject) => {
nativeShareWebpage?.(data);
emitter.once("SendMessageToWX.Resp", (resp) => {
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
});
});
}
/**
* Share miniProgram
* @method shareMiniProgram
* @param {Object} data
*/
export function shareMiniProgram(data: ShareMiniProgramMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
if (data && data.miniProgramType == null) {
data.miniProgramType = 0;
}
return new Promise((resolve, reject) => {
nativeShareMiniProgram?.(data);
emitter.once("SendMessageToWX.Resp", (resp) => {
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
});
});
}
/**
* 打开小程序
* @method launchMini
* @param
* @param {String} userName - 拉起的小程序的username
* @param {Integer} miniProgramType - 拉起小程序的类型. 0-正式版 1-开发版 2-体验版
* @param {String} path - 拉起小程序页面的可带参路径,不填默认拉起小程序首页
*/
export function launchMiniProgram({ userName, miniProgramType = 0, path = "" }: LaunchMiniProgramMetadata) {
return new Promise((resolve, reject) => {
if (miniProgramType !== 0 && miniProgramType !== 1 && miniProgramType !== 2) {
reject(
new WechatError({
errStr: "拉起小程序的类型不对,0-正式版 1-开发版 2-体验版",
errCode: -1,
})
);
return;
}
const onLaunchMiniRes = (resp: any) => {
WechatLib.unregisterCallback("WXLaunchMiniProgramReq.Resp");
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
};
WechatLib.registerCallback("WXLaunchMiniProgramReq.Resp", onLaunchMiniRes);
nativeLaunchMiniProgram?.({ userName, miniProgramType, path });
});
}
/**
* 一次性订阅消息
* @method shareVideo
* @param {Object} data
*/
export function subscribeMessage(data: SubscribeMessageMetadata) {
if (data && data.scene == null) {
data.scene = 0;
}
return new Promise((resolve, reject) => {
nativeSubscribeMessage?.(data);
emitter.once("WXSubscribeMsgReq.Resp", (resp) => {
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
});
});
}
interface PayResponse {
errCode: number;
errStr?: string;
[key: string]: any;
}
/**
* 支付
* @param data PaymentLoad
* @returns Promise<PayResponse>
*/
export function pay(data: PaymentLoad): Promise<PayResponse> {
function correct(actual: keyof PaymentLoad, fixed: keyof PaymentLoad) {
if (!data[fixed] && data[actual]) {
data[fixed] = data[actual];
delete data[actual];
}
}
correct("prepayid" as keyof PaymentLoad, "prepayId");
correct("noncestr" as keyof PaymentLoad, "nonceStr");
correct("partnerid" as keyof PaymentLoad, "partnerId");
correct("timestamp" as keyof PaymentLoad, "timeStamp");
data.timeStamp = String(data.timeStamp);
return new Promise((resolve, reject) => {
const onPayRes = (resp: any) => {
WechatLib.unregisterCallback("Pay.Resp");
if (resp.errCode === 0) {
resolve(resp);
} else {
reject(new WechatError(resp));
}
};
WechatLib.registerCallback("Pay.Resp", onPayRes);
WechatLib.pay(data, (result: any) => {
if (result) reject(result);
});
});
}
/**
* promises will reject with this error when API call finish with an errCode other than zero.
*/
interface WechatResponse {
errCode: number;
errStr?: string;
}
export class WechatError extends Error {
code: number;
constructor(resp: WechatResponse) {
const message = resp.errStr || resp.errCode.toString();
super(message);
this.name = "WechatError";
this.code = resp.errCode;
// 处理 Babel 对 Error 类继承的限制
if (typeof Object.setPrototypeOf === "function") {
Object.setPrototypeOf(this, WechatError.prototype);
} else {
// @ts-ignore
this.__proto__ = WechatError.prototype;
}
}
}