UNPKG

react-native-wxwork

Version:

react-native library for wxwork app

395 lines (359 loc) 11.5 kB
"use strict"; import { DeviceEventEmitter, NativeModules, Platform, NativeEventEmitter } from "react-native"; import { EventEmitter } from "events"; let isAppRegistered = false; const { RNWxwork } = NativeModules; // Event emitter to dispatch request and response from RNWxwork. const emitter = new EventEmitter(); const WXWorkEmitter = new NativeEventEmitter(RNWxwork); DeviceEventEmitter.addListener("WeChat_Resp", resp => { emitter.emit(resp.type, resp); }); function wrapRegisterApp(nativeFunc) { if (!nativeFunc) { return undefined; } return (...args) => { if (isAppRegistered) { // FIXME(Yorkie): we ignore this error if AppRegistered is true. return Promise.resolve(true); } isAppRegistered = true; return new Promise((resolve, reject) => { nativeFunc.apply(null, [ ...args, (error, result) => { if (!error) { return resolve(result); } if (typeof error === "string") { return reject(new Error(error)); } reject(error); } ]); }); }; } function wrapApi(nativeFunc) { if (!nativeFunc) { return undefined; } return (...args) => { if (!isAppRegistered) { return Promise.reject(new Error("registerApp required.")); } return new Promise((resolve, reject) => { nativeFunc.apply(null, [ ...args, (error, result) => { if (!error) { return resolve(result); } if (typeof error === "string") { return reject(new Error(error)); } reject(error); } ]); }); }; } /** * `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(RNWxwork.registerApp); /** * @method registerWWApp * @param {String} schema - schema * @return {Promise} */ export const registerWWApp = wrapRegisterApp(RNWxwork.registerWWApp); /** * @method registerAppWithDescription * @param {String} appid - the app id * @param {String} appdesc - the app description * @return {Promise} */ export const registerAppWithDescription = wrapRegisterApp( RNWxwork.registerAppWithDescription ); /** * Return if the wechat app is installed in the device. * @method isWXAppInstalled * @return {Promise} */ export const isWXAppInstalled = wrapApi(RNWxwork.isWXAppInstalled); /** * Return if the wechat app is installed in the device. * @method isWXAppInstalled * @return {Promise} */ export const isWWAppInstalled = wrapApi(RNWxwork.isWWAppInstalled); /** * Return if the wechat application supports the api * @method isWXAppSupportApi * @return {Promise} */ export const isWXAppSupportApi = wrapApi(RNWxwork.isWXAppSupportApi); /** * Return if the wechat application supports the api * @method isWWAppSupportApi * @return {Promise} */ export const isWWAppSupportApi = wrapApi(RNWxwork.isWWAppSupportApi); /** * Get the wechat app installed url * @method getWWAppInstallUrl * @return {String} the wechat app installed url */ export const getWWAppInstallUrl = wrapApi(RNWxwork.getWWAppInstallUrl); /** * Get the wechat app installed url * @method getWXAppInstallUrl * @return {String} the wechat app installed url */ export const getWXAppInstallUrl = wrapApi(RNWxwork.getWXAppInstallUrl); /** * Get the wechat api version * @method getApiVersion * @return {String} the api version string */ export const getApiVersion = wrapApi(RNWxwork.getApiVersion); /** * Get the wxwork api version * @method getWWApiVersion * @return {String} the api version string */ export const getWWApiVersion = wrapApi(RNWxwork.getWWApiVersion); /** * Open wechat app * @method openWXApp * @return {Promise} */ export const openWXApp = wrapApi(RNWxwork.openWXApp); /** * Open wxwork app * @method openWWApp * @return {Promise} */ export const openWWApp = wrapApi(RNWxwork.openWWApp); // wrap the APIs const nativeShareToTimeline = wrapApi(RNWxwork.shareToTimeline); const nativeShareToSession = wrapApi(RNWxwork.shareToSession); const nativeShareToFavorite = wrapApi(RNWxwork.shareToFavorite); const nativeSendAuthRequest = wrapApi(RNWxwork.sendAuthRequest); /** * @method sendAuthRequest * @param {Array} scopes - the scopes for authentication. * @return {Promise} */ export function sendAuthRequest(scopes, state) { return new Promise((resolve, reject) => { RNWxwork.sendAuthRequest(scopes, state, () => {}); emitter.once("SendAuth.Resp", resp => { if (resp.errCode === 0) { resolve(resp); } else { reject(new WechatError(resp)); } }); }); } /** * @method sendWWAuthRequest * @param {Array} schema - the scopes for authentication. * @return {Promise} */ export function sendWWAuthRequest(schema, appid, agentid) { return new Promise((resolve, reject) => { RNWxwork.sendWWAuthRequest(schema, appid, agentid, () => {}); emitter.once("SendAuth.Resp", resp => { if (resp.errCode === 0) { resolve(resp); } else { reject(new WechatError(resp)); } }); }); } /** * @method sendWWAuthRequest * @param {Array} schema - the scopes for authentication. * @return {Promise} */ export function sendSSORequest() { return new Promise((resolve, reject) => { RNWxwork.sendSSORequest(() => {}); emitter.once("SendAuth.Resp", resp => { console.log(resp); if (resp.errCode === 0) { resolve(resp); } else { reject(new WechatError(resp)); } }); }); } /** * Share something to timeline/moments/朋友圈 * @method shareToTimeline * @param {Object} data * @param {String} data.thumbImage - Thumb image of the message, which can be a uri or a resource id. * @param {String} data.type - Type of this message. Could be {news|text|imageUrl|imageFile|imageResource|video|audio|file} * @param {String} data.webpageUrl - Required if type equals news. The webpage link to share. * @param {String} data.imageUrl - Provide a remote image if type equals image. * @param {String} data.videoUrl - Provide a remote video if type equals video. * @param {String} data.musicUrl - Provide a remote music if type equals audio. * @param {String} data.filePath - Provide a local file if type equals file. * @param {String} data.fileExtension - Provide the file type if type equals file. */ export function shareToTimeline(data) { return new Promise((resolve, reject) => { nativeShareToTimeline(data); emitter.once("SendMessageToWX.Resp", resp => { if (resp.errCode === 0) { resolve(resp); } else { reject(new WechatError(resp)); } }); }); } /** * Share something to a friend or group * @method shareToSession * @param {Object} data * @param {String} data.thumbImage - Thumb image of the message, which can be a uri or a resource id. * @param {String} data.type - Type of this message. Could be {news|text|imageUrl|imageFile|imageResource|video|audio|file} * @param {String} data.webpageUrl - Required if type equals news. The webpage link to share. * @param {String} data.imageUrl - Provide a remote image if type equals image. * @param {String} data.videoUrl - Provide a remote video if type equals video. * @param {String} data.musicUrl - Provide a remote music if type equals audio. * @param {String} data.filePath - Provide a local file if type equals file. * @param {String} data.fileExtension - Provide the file type if type equals file. */ export function shareToSession(data) { return new Promise((resolve, reject) => { nativeShareToSession(data); emitter.once("SendMessageToWX.Resp", resp => { if (resp.errCode === 0) { resolve(resp); } else { reject(new WechatError(resp)); } }); }); } /** * Share something to favorite * @method shareToFavorite * @param {Object} data * @param {String} data.thumbImage - Thumb image of the message, which can be a uri or a resource id. * @param {String} data.type - Type of this message. Could be {news|text|imageUrl|imageFile|imageResource|video|audio|file} * @param {String} data.webpageUrl - Required if type equals news. The webpage link to share. * @param {String} data.imageUrl - Provide a remote image if type equals image. * @param {String} data.videoUrl - Provide a remote video if type equals video. * @param {String} data.musicUrl - Provide a remote music if type equals audio. * @param {String} data.filePath - Provide a local file if type equals file. * @param {String} data.fileExtension - Provide the file type if type equals file. */ export function shareToFavorite(data) { return new Promise((resolve, reject) => { nativeShareToFavorite(data); emitter.once("SendMessageToWX.Resp", resp => { if (resp.errCode === 0) { resolve(resp); } else { reject(new WechatError(resp)); } }); }); } /** * wechat pay * @param {Object} data * @param {String} data.partnerId * @param {String} data.prepayId * @param {String} data.nonceStr * @param {String} data.timeStamp * @param {String} data.package * @param {String} data.sign * @returns {Promise} */ export function pay(data) { // FIXME(Yorkie): see https://github.com/yorkie/react-native-wechat/issues/203 // Here the server-side returns params in lowercase, but here SDK requires timeStamp // for compatibility, we make this correction for users. function correct(actual, fixed) { if (!data[fixed] && data[actual]) { data[fixed] = data[actual]; delete data[actual]; } } correct("prepayid", "prepayId"); correct("noncestr", "nonceStr"); correct("partnerid", "partnerId"); correct("timestamp", "timeStamp"); // FIXME(94cstyles) // Android requires the type of the timeStamp field to be a string if (Platform.OS === "android") data.timeStamp = String(data.timeStamp); return new Promise((resolve, reject) => { RNWxwork.pay(data, result => { if (result) reject(result); }); emitter.once("PayReq.Resp", resp => { if (resp.errCode === 0) { resolve(resp); } else { reject(new WechatError(resp)); } }); }); } /** * promises will reject with this error when API call finish with an errCode other than zero. */ export class WechatError extends Error { constructor(resp) { const message = resp.errStr || resp.errCode.toString(); super(message); this.name = "WechatError"; this.code = resp.errCode; // avoid babel's limition about extending Error class // https://github.com/babel/babel/issues/3083 if (typeof Object.setPrototypeOf === "function") { Object.setPrototypeOf(this, WechatError.prototype); } else { this.__proto__ = WechatError.prototype; } } } export default RNWxwork;