├── README.md ├── package.json ├── plugin.xml ├── scripts ├── android-install.js └── wp-install.js ├── src ├── android │ ├── WXEntryActivity.java │ ├── WeChat.java │ └── libammsdk.jar ├── ios │ ├── CDVWeChat.h │ ├── CDVWeChat.m │ ├── WXApi.h │ ├── WXApiObject.h │ └── libWeChatSDK.a └── wp │ ├── Google.ProtocolBuffersLite.dll │ ├── MicroMsgSDK.dll │ ├── WeChat.cs │ ├── WeChatCallbackPage.xaml │ └── WeChatCallbackPage.xaml.cs └── www └── wechat.js /README.md: -------------------------------------------------------------------------------- 1 | # Cordova/PhoneGap 微信分享插件 2 | 3 | 此插件暂停维护, 如果不需要 WP 平台支持, 请使用 https://github.com/xu-li/cordova-plugin-wechat. 4 | 5 | Inspired by https://github.com/xu-li/cordova-plugin-wechat 6 | 7 | 支持 iOS, WP, Android, 都有回调. 分享内容只支持文本, 图片, 和链接. 8 | 9 | **另外需要注意的是 Android 不仅需要审核通过, 还需要那什么签名吻合, 所以得要 release 的 keystore 来签名.** 10 | 关于这个问题写了个指南, 如果 Android 搞不定的可以看看 11 | [Android 微信 SDK 签名问题](https://github.com/vilic/cordova-plugin-wechat/wiki/Android-%E5%BE%AE%E4%BF%A1-SDK-%E7%AD%BE%E5%90%8D%E9%97%AE%E9%A2%98). 12 | 13 | ## 安装 14 | 15 | 一定不要忘记加上后面的 `--variable APP_ID=********`. 16 | 17 | ```sh 18 | cordova plugin add cordova-plugin-tx-wechat --variable APP_ID=[你的APPID] 19 | ``` 20 | 21 | 另外貌似 Cordova 的变量信息是按平台保存的, 如果安装插件时尚未添加某个平台, 即便之前加上了变量, 22 | 之后添加平台时依旧会报错. 此时可以先卸载插件, 添加平台后带上变量重新安装. 23 | 24 | 如果是 Visual Studio Tools for Apache Cordova, 可以这样配置 App ID: 25 | 26 | ```xml 27 | 28 | 29 | 30 | ``` 31 | 32 | ## 配置 33 | 34 | 其实安装后就可以用了! 零配置哟哈哈哈! 下面列一些注意事项. 35 | 36 | ### config.xml 37 | 38 | **可能**需要添加一些权限, 比如安卓貌似是要添加这些: 39 | 40 | ```xml 41 | 42 | 43 | 44 | 45 | 46 | 47 | ``` 48 | 49 | 反正我没添加, debug/release 都没问题, 不知道提交商店会不会有情况. 50 | 51 | ### iOS 相关: libWeChatSDK.a 52 | 53 | src/ios/libWeChatSDK.a 这个文件有两个版本, 一个是 iPhone Only 的, 要小一些, 应该是最后生产环境用的. 54 | 我放进去的是完整版本, 要大一倍 (应该是包含了 x86 架构方便模拟器 debug), 可以自己去下载 55 | [官方 SDK](https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list) 56 | 然后替换掉 platforms/ios/应用名称/Plugins 目录下的 libWeChatSDK.a. 57 | 58 | ## 使用 59 | 60 | ```javascript 61 | // 在 device ready 后. 62 | 63 | // 分享 API 64 | WeChat 65 | .share('文本', WeChat.Scene.session, function () { 66 | console.log('分享成功~'); 67 | }, function (reason) { 68 | console.log(reason); 69 | }); 70 | 71 | // 或者 (更多选项见后). 72 | WeChat 73 | .share({ 74 | type: WeChat.ShareType.webpage, 75 | title: '链接', 76 | description: '链接描述', 77 | url: 'https://wordsbaking.com/' 78 | }, WeChat.Scene.timeline, function () { 79 | console.log('分享成功~'); 80 | }, function (reason) { 81 | // 分享失败 82 | console.log(reason); 83 | }); 84 | 85 | // 检查微信安装情况 86 | // WP 始终返回 true 87 | WeChat 88 | .isInstalled(function(installed) { 89 | console.log('WeChat installed='+installed); 90 | }, function(reason) { 91 | console.log(reason); 92 | }); 93 | ``` 94 | 95 | ## API 定义 96 | 97 | ```typescript 98 | declare module WeChat { 99 | /** 分享场景 */ 100 | enum Scene { 101 | /** 用户自选, 安卓不支持 */ 102 | chosenByUser, 103 | /** 聊天 */ 104 | session, 105 | /** 朋友圈 */ 106 | timeline 107 | } 108 | 109 | /** 多媒体分享类型, 目前只支持 image, webpage */ 110 | enum ShareType { 111 | app = 1, 112 | emotion, 113 | file, 114 | image, 115 | music, 116 | video, 117 | webpage 118 | } 119 | 120 | /** 分享选项 */ 121 | interface IMessageOptions { 122 | /** 多媒体类型, 默认为 webpage */ 123 | type: ShareType; 124 | /** 标题 */ 125 | title?: string; 126 | /** 描述 */ 127 | description?: string; 128 | /** 缩略图的 base 64 字符串 */ 129 | thumbData?: string; 130 | /** 分享内容的 url, type 为 image 是就是图片的 url, 为 webpage 时就是链接的 url */ 131 | url?: string; 132 | /** 分享内容的 base 64 字符串, 与 url 二选一 */ 133 | data?: string; 134 | } 135 | 136 | // 分享. 137 | function share(text: string, scene: Scene, onfulfilled: () => void, onrejected: (reason) => void): void; 138 | function share(options: IMessageOptions, scene: Scene, onfulfilled: () => void, onrejected: (reason) => void): void; 139 | } 140 | ``` 141 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-tx-wechat", 3 | "version": "0.3.2", 4 | "description": "Cordova WeChat Plugin", 5 | "cordova": { 6 | "id": "cordova-plugin-tx-wechat", 7 | "platforms": [ 8 | "ios", 9 | "wp8", 10 | "android" 11 | ] 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/vilic/cordova-plugin-wechat.git" 16 | }, 17 | "keywords": [ 18 | "ecosystem:cordova", 19 | "cordova", 20 | "wechat", 21 | "weixin", 22 | "微信", 23 | "cordova-ios", 24 | "cordova-wp8", 25 | "cordova-android" 26 | ], 27 | "author": "VILIC VANE", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/vilic/cordova-plugin-wechat/issues" 31 | }, 32 | "homepage": "https://github.com/vilic/cordova-plugin-wechat#readme" 33 | } 34 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | WeChat 9 | Cordova WeChat Plugin 10 | VILIC VANE 11 | MIT 12 | ecosystem:cordova,cordova,wechat,weixin,微信 13 | https://github.com/vilic/cordova-plugin-wechat.git 14 | https://github.com/vilic/cordova-plugin-wechat/issues 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | CFBundleURLName 35 | weixin 36 | CFBundleURLSchemes 37 | 38 | $APP_ID 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 注意: 内置的 iOS SDK 在发布应用时应该替换 60 | src/ios/libWeChatSDK.a 这个文件有两个版本, 一个是 iPhone Only 的, 要小一些, 应该是最后生产环境用的. 我放进去的是完整版本, 要大一倍 (应该是包含了 x86 架构方便模拟器 debug), 可以自己去下载官方 SDK 然后替换掉 platforms/ios/应用名称/Plugins 目录下的 libWeChatSDK.a. 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | .$APP_ID 83 | .wechatapp 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /scripts/android-install.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | module.exports = function (context) { 4 | var options = context.opts; 5 | var projectConfigFile = options.projectRoot + '/config.xml'; 6 | 7 | var projectIdRegex = /]*\sid=(["'])((?:(?!\1|\s).)+)/i; 8 | 9 | var configXml = fs.readFileSync(projectConfigFile, 'utf-8'); 10 | 11 | var projectId = (configXml.match(projectIdRegex) || [])[2]; 12 | 13 | if (!projectId) { 14 | throw new Error('missing project id'); 15 | } 16 | 17 | var wechatEntryFile = 'WXEntryActivity.java'; 18 | var androidSrcDir = options.projectRoot + '/platforms/android/src/'; 19 | var wxapiDir = projectId.replace(/\./g, '/') + '/wxapi/'; 20 | 21 | var entryJavaFileTarget = androidSrcDir + wxapiDir + wechatEntryFile; 22 | 23 | if (context.hook == 'after_plugin_install') { 24 | var entryJavaFile = options.plugin.dir + '/src/android/' + wechatEntryFile; 25 | var entryJavaCode = fs.readFileSync(entryJavaFile, 'utf-8'); 26 | 27 | entryJavaCode = entryJavaCode.replace(/^package .+/m, 'package ' + projectId + '.wxapi;'); 28 | 29 | var dirPartRegex = /[^\\\/]+[\\\/]*/g; 30 | var dirPartGroups; 31 | var dirToCreate = androidSrcDir; 32 | 33 | while (dirPartGroups = dirPartRegex.exec(wxapiDir)) { 34 | dirToCreate += dirPartGroups[0]; 35 | 36 | if (!fs.existsSync(dirToCreate)) { 37 | fs.mkdirSync(dirToCreate); 38 | } 39 | } 40 | 41 | fs.writeFileSync(entryJavaFileTarget, entryJavaCode); 42 | } else { 43 | try { 44 | fs.unlinkSync(entryJavaFileTarget); 45 | fs.rmdirSync(androidSrcDir + wxapiDir); 46 | } catch (e) { } 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /scripts/wp-install.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | 3 | module.exports = function (context) { 4 | var options = context.opts; 5 | 6 | var appXamlCsFile = options.projectRoot + '\\platforms\\wp8\\App.xaml.cs'; 7 | var appXamlCsCode = fs.readFileSync(appXamlCsFile, 'utf-8'); 8 | 9 | if (context.hook == 'after_plugin_install') { 10 | if (/\bWeChatAssociationUriMapper\b/.test(appXamlCsCode)) { 11 | return; 12 | } 13 | 14 | appXamlCsCode = appXamlCsCode 15 | .replace(/^((?:(?![\r\n])\s)*)RootFrame\s*=\s*new\s+PhoneApplicationFrame\(\);/m, function (m, spaces) { 16 | return m + '\r\n\r\n' + 17 | spaces + '// Added by cordova-plugin-tx-wechat.\r\n' + 18 | spaces + 'RootFrame.UriMapper = new WeChatAssociationUriMapper(RootFrame.UriMapper);\r\n'; 19 | }); 20 | } else { 21 | appXamlCsCode = appXamlCsCode 22 | .replace(/\r?\n(?:(?:(?![\r\n])\s)*\/\/.+\r?\n)?\s*RootFrame\s*\.\s*UriMapper\s*=\s*new\s+WeChatAssociationUriMapper\(\s*RootFrame\s*\.\s*UriMapper\s*\)\s*;\s*\r?\n/m, ''); 23 | } 24 | 25 | fs.writeFileSync(appXamlCsFile, appXamlCsCode); 26 | 27 | if (context.hook == 'after_plugin_install') { 28 | var wmAppManifestFile = options.projectRoot + '\\platforms\\wp8\\Properties\\WMAppManifest.xml'; 29 | var wmAppManifestXml = fs.readFileSync(wmAppManifestFile, 'utf-8'); 30 | 31 | wmAppManifestXml = wmAppManifestXml 32 | .replace(/]*Name="_default"[^>]*\/?>/, function (m) { 33 | return m 34 | .replace(/\bActivationPolicy\s*=\s*"[^"]*"\s?/, '') 35 | .replace(/(\s?\/?>)$/, ' ActivationPolicy="Resume"$1'); 36 | }); 37 | 38 | fs.writeFileSync(wmAppManifestFile, wmAppManifestXml); 39 | } 40 | }; -------------------------------------------------------------------------------- /src/android/WXEntryActivity.java: -------------------------------------------------------------------------------- 1 | package to.be.replaced.wxapi; 2 | 3 | import com.tencent.mm.sdk.openapi.IWXAPIEventHandler; 4 | import com.tencent.mm.sdk.modelbase.BaseReq; 5 | import com.tencent.mm.sdk.modelbase.BaseResp; 6 | 7 | import android.app.Activity; 8 | import android.content.Intent; 9 | import android.os.Bundle; 10 | 11 | import com.wordsbaking.cordova.wechat.WeChat; 12 | 13 | /* 14 | Cordova WeChat Plugin 15 | https://github.com/vilic/cordova-plugin-wechat 16 | 17 | by VILIC VANE 18 | https://github.com/vilic 19 | 20 | MIT License 21 | */ 22 | 23 | public class WXEntryActivity extends Activity implements IWXAPIEventHandler{ 24 | @Override 25 | public void onCreate(Bundle savedInstanceState) { 26 | try { 27 | super.onCreate(savedInstanceState); 28 | WeChat.api.handleIntent(getIntent(), this); 29 | } catch (Exception e) { 30 | finish(); 31 | } 32 | } 33 | 34 | @Override 35 | protected void onNewIntent(Intent intent) { 36 | super.onNewIntent(intent); 37 | setIntent(intent); 38 | WeChat.api.handleIntent(intent, this); 39 | } 40 | 41 | @Override 42 | public void onReq(BaseReq req) { 43 | // not implemented 44 | finish(); 45 | } 46 | 47 | @Override 48 | public void onResp(BaseResp resp) { 49 | switch (resp.errCode) { 50 | case BaseResp.ErrCode.ERR_OK: 51 | WeChat.currentCallbackContext.success(); 52 | break; 53 | case BaseResp.ErrCode.ERR_USER_CANCEL: 54 | WeChat.currentCallbackContext.error(WeChat.ERR_USER_CANCEL); 55 | break; 56 | case BaseResp.ErrCode.ERR_AUTH_DENIED: 57 | WeChat.currentCallbackContext.error(WeChat.ERR_AUTH_DENIED); 58 | break; 59 | case BaseResp.ErrCode.ERR_SENT_FAILED: 60 | WeChat.currentCallbackContext.error(WeChat.ERR_SENT_FAILED); 61 | break; 62 | case BaseResp.ErrCode.ERR_UNSUPPORT: 63 | WeChat.currentCallbackContext.error(WeChat.ERR_UNSUPPORT); 64 | break; 65 | case BaseResp.ErrCode.ERR_COMM: 66 | WeChat.currentCallbackContext.error(WeChat.ERR_COMM); 67 | break; 68 | default: 69 | WeChat.currentCallbackContext.error(WeChat.ERR_UNKNOWN); 70 | break; 71 | } 72 | finish(); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/android/WeChat.java: -------------------------------------------------------------------------------- 1 | package com.wordsbaking.cordova.wechat; 2 | 3 | import org.apache.cordova.CallbackContext; 4 | import org.apache.cordova.CordovaPlugin; 5 | import org.apache.cordova.PluginResult; 6 | 7 | import org.apache.cordova.CordovaWebView; 8 | import org.apache.cordova.CordovaInterface; 9 | 10 | import org.json.JSONArray; 11 | import org.json.JSONException; 12 | import org.json.JSONObject; 13 | 14 | import android.util.Base64; 15 | 16 | import com.tencent.mm.sdk.openapi.IWXAPI; 17 | import com.tencent.mm.sdk.openapi.WXAPIFactory; 18 | import com.tencent.mm.sdk.modelmsg.SendMessageToWX; 19 | import com.tencent.mm.sdk.modelmsg.WXMediaMessage; 20 | import com.tencent.mm.sdk.modelmsg.WXTextObject; 21 | import com.tencent.mm.sdk.modelmsg.WXImageObject; 22 | import com.tencent.mm.sdk.modelmsg.WXWebpageObject; 23 | 24 | /* 25 | Cordova WeChat Plugin 26 | https://github.com/vilic/cordova-plugin-wechat 27 | 28 | by VILIC VANE 29 | https://github.com/vilic 30 | 31 | MIT License 32 | */ 33 | 34 | public class WeChat extends CordovaPlugin { 35 | 36 | public static final String WECHAT_APPID_KEY = "wechatappid"; 37 | 38 | public static final String ERR_WECHAT_NOT_INSTALLED = "ERR_WECHAT_NOT_INSTALLED"; 39 | public static final String ERR_INVALID_OPTIONS = "ERR_INVALID_OPTIONS"; 40 | public static final String ERR_UNSUPPORTED_MEDIA_TYPE = "ERR_UNSUPPORTED_MEDIA_TYPE"; 41 | public static final String ERR_USER_CANCEL = "ERR_USER_CANCEL"; 42 | public static final String ERR_AUTH_DENIED = "ERR_AUTH_DENIED"; 43 | public static final String ERR_SENT_FAILED = "ERR_SENT_FAILED"; 44 | public static final String ERR_UNSUPPORT = "ERR_UNSUPPORT"; 45 | public static final String ERR_COMM = "ERR_COMM"; 46 | public static final String ERR_UNKNOWN = "ERR_UNKNOWN"; 47 | public static final String NO_RESULT = "NO_RESULT"; 48 | 49 | public static final int SHARE_TYPE_APP = 1; 50 | public static final int SHARE_TYPE_EMOTION = 2; 51 | public static final int SHARE_TYPE_FILE = 3; 52 | public static final int SHARE_TYPE_IMAGE = 4; 53 | public static final int SHARE_TYPE_MUSIC = 5; 54 | public static final int SHARE_TYPE_VIDEO = 6; 55 | public static final int SHARE_TYPE_WEBPAGE = 7; 56 | 57 | public static final int SCENE_CHOSEN_BY_USER = 0; 58 | public static final int SCENE_SESSION = 1; 59 | public static final int SCENE_TIMELINE = 2; 60 | 61 | public static IWXAPI api; 62 | public static CallbackContext currentCallbackContext; 63 | 64 | @Override 65 | public void initialize(CordovaInterface cordova, CordovaWebView webView) { 66 | String appId = preferences.getString(WECHAT_APPID_KEY, ""); 67 | api = WXAPIFactory.createWXAPI(webView.getContext(), appId, true); 68 | api.registerApp(appId); 69 | } 70 | 71 | @Override 72 | public boolean execute(String action, JSONArray args, CallbackContext callbackContext) 73 | throws JSONException { 74 | if (action.equals("share")) { 75 | share(args, callbackContext); 76 | } else if (action.equals("isInstalled")) { 77 | isInstalled(callbackContext); 78 | } else { 79 | return false; 80 | } 81 | return true; 82 | } 83 | 84 | private void share(JSONArray args, CallbackContext callbackContext) 85 | throws JSONException, NullPointerException { 86 | // check if installed 87 | if (!api.isWXAppInstalled()) { 88 | callbackContext.error(ERR_WECHAT_NOT_INSTALLED); 89 | return; 90 | } 91 | 92 | JSONObject params = args.getJSONObject(0); 93 | 94 | if (params == null) { 95 | callbackContext.error(ERR_INVALID_OPTIONS); 96 | return; 97 | } 98 | 99 | SendMessageToWX.Req request = new SendMessageToWX.Req(); 100 | 101 | request.transaction = String.valueOf(System.currentTimeMillis()); 102 | 103 | int paramScene = params.getInt("scene"); 104 | 105 | switch (paramScene) { 106 | case SCENE_SESSION: 107 | request.scene = SendMessageToWX.Req.WXSceneSession; 108 | break; 109 | // wechat android sdk does not support chosen by user 110 | case SCENE_CHOSEN_BY_USER: 111 | case SCENE_TIMELINE: 112 | default: 113 | request.scene = SendMessageToWX.Req.WXSceneTimeline; 114 | break; 115 | } 116 | 117 | WXMediaMessage message = null; 118 | 119 | String text = null; 120 | JSONObject messageOptions = null; 121 | 122 | if (!params.isNull("text")) { 123 | text = params.getString("text"); 124 | } 125 | 126 | if (!params.isNull("message")) { 127 | messageOptions = params.getJSONObject("message"); 128 | } 129 | 130 | if (messageOptions != null) { 131 | String url = null; 132 | String data = null; 133 | 134 | if (!messageOptions.isNull("url")) { 135 | url = messageOptions.getString("url"); 136 | } 137 | 138 | if (!messageOptions.isNull("data")) { 139 | data = messageOptions.getString("data"); 140 | } 141 | 142 | int type = SHARE_TYPE_WEBPAGE; 143 | 144 | if (!messageOptions.isNull("type")) { 145 | type = messageOptions.getInt("type"); 146 | } 147 | 148 | switch (type) { 149 | case SHARE_TYPE_APP: 150 | break; 151 | case SHARE_TYPE_EMOTION: 152 | break; 153 | case SHARE_TYPE_FILE: 154 | break; 155 | case SHARE_TYPE_IMAGE: 156 | WXImageObject imageObject = new WXImageObject(); 157 | if (url != null) { 158 | imageObject.imageUrl = url; 159 | } else if (data != null) { 160 | imageObject.imageData = Base64.decode(data, Base64.DEFAULT); 161 | } else { 162 | callbackContext.error(ERR_INVALID_OPTIONS); 163 | return; 164 | } 165 | message = new WXMediaMessage(imageObject); 166 | break; 167 | case SHARE_TYPE_MUSIC: 168 | break; 169 | case SHARE_TYPE_VIDEO: 170 | break; 171 | case SHARE_TYPE_WEBPAGE: 172 | default: 173 | WXWebpageObject webpageObject = new WXWebpageObject(); 174 | webpageObject.webpageUrl = url; 175 | message = new WXMediaMessage(webpageObject); 176 | break; 177 | } 178 | 179 | if (message == null) { 180 | callbackContext.error(ERR_UNSUPPORTED_MEDIA_TYPE); 181 | return; 182 | } 183 | 184 | if (!messageOptions.isNull("title")) { 185 | message.title = messageOptions.getString("title"); 186 | } 187 | 188 | if (!messageOptions.isNull("description")) { 189 | message.description = messageOptions.getString("description"); 190 | } 191 | 192 | if (!messageOptions.isNull("thumbData")) { 193 | String thumbData = messageOptions.getString("thumbData"); 194 | message.thumbData = Base64.decode(thumbData, Base64.DEFAULT); 195 | } 196 | } else if (text != null) { 197 | WXTextObject textObject = new WXTextObject(); 198 | textObject.text = text; 199 | 200 | message = new WXMediaMessage(textObject); 201 | message.description = text; 202 | } else { 203 | callbackContext.error(ERR_INVALID_OPTIONS); 204 | return; 205 | } 206 | 207 | request.message = message; 208 | 209 | try { 210 | boolean success = api.sendReq(request); 211 | if (!success) { 212 | callbackContext.error(ERR_UNKNOWN); 213 | return; 214 | } 215 | } catch (Exception e) { 216 | callbackContext.error(e.getMessage()); 217 | return; 218 | } 219 | 220 | currentCallbackContext = callbackContext; 221 | } 222 | 223 | private void isInstalled(CallbackContext callbackContext) { 224 | try { 225 | callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, api.isWXAppInstalled())); 226 | } catch (Exception e) { 227 | callbackContext.error(e.getMessage()); 228 | return; 229 | } 230 | 231 | currentCallbackContext = callbackContext; 232 | } 233 | } -------------------------------------------------------------------------------- /src/android/libammsdk.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vilicvane/cordova-plugin-wechat/3e81767d1099865cda3ba1dc57a38f8cac829f57/src/android/libammsdk.jar -------------------------------------------------------------------------------- /src/ios/CDVWeChat.h: -------------------------------------------------------------------------------- 1 | /* 2 | Cordova WeChat Plugin 3 | https://github.com/vilic/cordova-plugin-wechat 4 | 5 | by VILIC VANE 6 | https://github.com/vilic 7 | 8 | MIT License 9 | */ 10 | 11 | #import 12 | #import "WXApi.h" 13 | 14 | enum CDVWeChatShareType { 15 | CDVWeChatShareTypeApp = 1, 16 | CDVWeChatShareTypeEmotion, 17 | CDVWeChatShareTypeFile, 18 | CDVWeChatShareTypeImage, 19 | CDVWeChatShareTypeMusic, 20 | CDVWeChatShareTypeVideo, 21 | CDVWeChatShareTypeWebpage 22 | }; 23 | 24 | @interface CDVWeChat: CDVPlugin 25 | 26 | @property (nonatomic, strong) NSString *currentCallbackId; 27 | @property (nonatomic, strong) NSString *wechatAppId; 28 | 29 | - (void)share:(CDVInvokedUrlCommand *)command; 30 | - (void)isInstalled:(CDVInvokedUrlCommand *)command; 31 | 32 | @end -------------------------------------------------------------------------------- /src/ios/CDVWeChat.m: -------------------------------------------------------------------------------- 1 | /* 2 | Cordova WeChat Plugin 3 | https://github.com/vilic/cordova-plugin-wechat 4 | 5 | by VILIC VANE 6 | https://github.com/vilic 7 | 8 | MIT License 9 | */ 10 | 11 | #import 12 | #import "CDVWeChat.h" 13 | 14 | NSString* WECHAT_APPID_KEY = @"wechatappid"; 15 | NSString* ERR_WECHAT_NOT_INSTALLED = @"ERR_WECHAT_NOT_INSTALLED"; 16 | NSString* ERR_INVALID_OPTIONS = @"ERR_INVALID_OPTIONS"; 17 | NSString* ERR_UNSUPPORTED_MEDIA_TYPE = @"ERR_UNSUPPORTED_MEDIA_TYPE"; 18 | NSString* ERR_USER_CANCEL = @"ERR_USER_CANCEL"; 19 | NSString* ERR_AUTH_DENIED = @"ERR_AUTH_DENIED"; 20 | NSString* ERR_SENT_FAILED = @"ERR_SENT_FAILED"; 21 | NSString* ERR_COMM = @"ERR_COMM"; 22 | NSString* ERR_UNSUPPORT = @"ERR_UNSUPPORT"; 23 | NSString* ERR_UNKNOWN = @"ERR_UNKNOWN"; 24 | NSString* NO_RESULT = @"NO_RESULT"; 25 | 26 | const int SCENE_CHOSEN_BY_USER = 0; 27 | const int SCENE_SESSION = 1; 28 | const int SCENE_TIMELINE = 2; 29 | 30 | @implementation CDVWeChat 31 | 32 | - (void)pluginInitialize { 33 | NSString* appId = [[self.commandDelegate settings] objectForKey:WECHAT_APPID_KEY]; 34 | [WXApi registerApp: appId]; 35 | } 36 | 37 | - (void)share:(CDVInvokedUrlCommand*)command { 38 | CDVPluginResult* result = nil; 39 | 40 | if (![WXApi isWXAppInstalled]) { 41 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_WECHAT_NOT_INSTALLED]; 42 | [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 43 | return ; 44 | } 45 | 46 | NSDictionary* params = [command.arguments objectAtIndex:0]; 47 | if (!params) { 48 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_INVALID_OPTIONS]; 49 | [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 50 | return ; 51 | } 52 | 53 | SendMessageToWXReq* request = [SendMessageToWXReq new]; 54 | 55 | if ([params objectForKey:@"scene"]) { 56 | int paramScene = [[params objectForKey:@"scene"] integerValue]; 57 | 58 | switch (paramScene) { 59 | case SCENE_SESSION: 60 | request.scene = WXSceneSession; 61 | break; 62 | case SCENE_CHOSEN_BY_USER: 63 | case SCENE_TIMELINE: 64 | default: 65 | request.scene = WXSceneTimeline; 66 | break; 67 | } 68 | } else { 69 | request.scene = WXSceneTimeline; 70 | } 71 | 72 | NSDictionary* messageOptions = [params objectForKey:@"message"]; 73 | NSString* text = [params objectForKey:@"text"]; 74 | 75 | if ((id)messageOptions == [NSNull null]) { 76 | messageOptions = nil; 77 | } 78 | if ((id)text == [NSNull null]) { 79 | text = nil; 80 | } 81 | 82 | if (messageOptions) { 83 | request.bText = NO; 84 | 85 | NSString* url = [messageOptions objectForKey:@"url"]; 86 | NSString* data = [messageOptions objectForKey:@"data"]; 87 | 88 | if ((id)url == [NSNull null]) { 89 | url = nil; 90 | } 91 | if ((id)data == [NSNull null]) { 92 | data = nil; 93 | } 94 | 95 | WXMediaMessage* message = [WXMediaMessage message]; 96 | id mediaObject = nil; 97 | 98 | int type = [[messageOptions objectForKey:@"type"] integerValue]; 99 | 100 | if (!type) { 101 | type = CDVWeChatShareTypeWebpage; 102 | } 103 | 104 | switch (type) { 105 | case CDVWeChatShareTypeApp: 106 | break; 107 | case CDVWeChatShareTypeEmotion: 108 | break; 109 | case CDVWeChatShareTypeFile: 110 | break; 111 | case CDVWeChatShareTypeImage: 112 | mediaObject = [WXImageObject object]; 113 | if (url) { 114 | ((WXImageObject*)mediaObject).imageUrl = url; 115 | } else if (data) { 116 | ((WXImageObject*)mediaObject).imageData = [self decodeBase64:data]; 117 | } else { 118 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_INVALID_OPTIONS]; 119 | [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 120 | return ; 121 | } 122 | break; 123 | case CDVWeChatShareTypeMusic: 124 | break; 125 | case CDVWeChatShareTypeVideo: 126 | break; 127 | case CDVWeChatShareTypeWebpage: 128 | default: 129 | mediaObject = [WXWebpageObject object]; 130 | ((WXWebpageObject*)mediaObject).webpageUrl = url; 131 | break; 132 | } 133 | 134 | if (!mediaObject) { 135 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_UNSUPPORTED_MEDIA_TYPE]; 136 | [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 137 | return ; 138 | } 139 | 140 | message.mediaObject = mediaObject; 141 | 142 | message.title = [messageOptions objectForKey:@"title"]; 143 | message.description = [messageOptions objectForKey:@"description"]; 144 | 145 | NSString* thumbData = [messageOptions objectForKey:@"thumbData"]; 146 | 147 | if ((id)thumbData == [NSNull null]) { 148 | thumbData = nil; 149 | } 150 | 151 | if (thumbData) { 152 | message.thumbData = [self decodeBase64:thumbData]; 153 | } 154 | 155 | request.message = message; 156 | } else if (text) { 157 | request.bText = YES; 158 | request.text = text; 159 | } else { 160 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_INVALID_OPTIONS]; 161 | [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 162 | return ; 163 | } 164 | 165 | BOOL success = [WXApi sendReq:request]; 166 | 167 | if (success) { 168 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 169 | [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 170 | } else { 171 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_UNKNOWN]; 172 | [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; 173 | return; 174 | } 175 | 176 | self.currentCallbackId = command.callbackId; 177 | } 178 | 179 | - (NSData*)decodeBase64:(NSString*)base64String { 180 | NSString* dataUrl =[NSString stringWithFormat:@"data:application/octet-stream;base64,%@", base64String]; 181 | NSURL* url = [NSURL URLWithString: dataUrl]; 182 | return [NSData dataWithContentsOfURL:url]; 183 | } 184 | 185 | - (void)onResp:(BaseResp*)resp { 186 | if (!self.currentCallbackId) { 187 | return; 188 | } 189 | 190 | CDVPluginResult* result = nil; 191 | 192 | if([resp isKindOfClass:[SendMessageToWXResp class]]) { 193 | switch (resp.errCode) { 194 | case WXSuccess: 195 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 196 | break; 197 | case WXErrCodeUserCancel: 198 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_USER_CANCEL]; 199 | break; 200 | case WXErrCodeSentFail: 201 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_SENT_FAILED]; 202 | break; 203 | case WXErrCodeAuthDeny: 204 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_AUTH_DENIED]; 205 | break; 206 | case WXErrCodeUnsupport: 207 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_UNSUPPORT]; 208 | break; 209 | case WXErrCodeCommon: 210 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_COMM]; 211 | break; 212 | default: 213 | result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:ERR_UNKNOWN]; 214 | break; 215 | } 216 | } 217 | 218 | [self.commandDelegate sendPluginResult:result callbackId:self.currentCallbackId]; 219 | 220 | self.currentCallbackId = nil; 221 | } 222 | 223 | - (void)handleOpenURL:(NSNotification*)notification { 224 | NSURL* url = [notification object]; 225 | 226 | if ([url isKindOfClass:[NSURL class]] && [url.scheme isEqualToString:self.wechatAppId]) { 227 | [WXApi handleOpenURL:url delegate:self]; 228 | } 229 | } 230 | 231 | - (void)isInstalled:(CDVInvokedUrlCommand*)command { 232 | CDVPluginResult *commandResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:[WXApi isWXAppInstalled]]; 233 | 234 | [self.commandDelegate sendPluginResult:commandResult callbackId:command.callbackId]; 235 | } 236 | 237 | @end -------------------------------------------------------------------------------- /src/ios/WXApi.h: -------------------------------------------------------------------------------- 1 | // 2 | // WXApi.h 3 | // 所有Api接口 4 | // 5 | // Created by Wechat on 12-2-28. 6 | // Copyright (c) 2012年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "WXApiObject.h" 11 | 12 | 13 | #pragma mark - WXApiDelegate 14 | /*! @brief 接收并处理来自微信终端程序的事件消息 15 | * 16 | * 接收并处理来自微信终端程序的事件消息,期间微信界面会切换到第三方应用程序。 17 | * WXApiDelegate 会在handleOpenURL:delegate:中使用并触发。 18 | */ 19 | @protocol WXApiDelegate 20 | @optional 21 | 22 | /*! @brief 收到一个来自微信的请求,第三方应用程序处理完后调用sendResp向微信发送结果 23 | * 24 | * 收到一个来自微信的请求,异步处理完成后必须调用sendResp发送处理结果给微信。 25 | * 可能收到的请求有GetMessageFromWXReq、ShowMessageFromWXReq等。 26 | * @param req 具体请求内容,是自动释放的 27 | */ 28 | -(void) onReq:(BaseReq*)req; 29 | 30 | 31 | 32 | /*! @brief 发送一个sendReq后,收到微信的回应 33 | * 34 | * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。 35 | * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。 36 | * @param resp具体的回应内容,是自动释放的 37 | */ 38 | -(void) onResp:(BaseResp*)resp; 39 | 40 | @end 41 | 42 | 43 | 44 | #pragma mark - WXApi 45 | 46 | /*! @brief 微信Api接口函数类 47 | * 48 | * 该类封装了微信终端SDK的所有接口 49 | */ 50 | @interface WXApi : NSObject 51 | 52 | /*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。 53 | * 54 | * 需要在每次启动第三方应用程序时调用。第一次调用后,会在微信的可用应用列表中出现。 55 | * iOS7及以上系统需要调起一次微信才会出现在微信的可用应用列表中。 56 | * @attention 请保证在主线程中调用此函数 57 | * @param appid 微信开发者ID 58 | * @return 成功返回YES,失败返回NO。 59 | */ 60 | +(BOOL) registerApp:(NSString *)appid; 61 | 62 | 63 | 64 | /*! @brief WXApi的成员函数,向微信终端程序注册第三方应用。 65 | * 66 | * 需要在每次启动第三方应用程序时调用。第一次调用后,会在微信的可用应用列表中出现。 67 | * @see registerApp 68 | * @param appid 微信开发者ID 69 | * @param appdesc 应用附加信息,长度不超过1024字节 70 | * @return 成功返回YES,失败返回NO。 71 | */ 72 | +(BOOL) registerApp:(NSString *)appid withDescription:(NSString *)appdesc; 73 | 74 | 75 | 76 | /*! @brief 处理微信通过URL启动App时传递的数据 77 | * 78 | * 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。 79 | * @param url 微信启动第三方应用时传递过来的URL 80 | * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 81 | * @return 成功返回YES,失败返回NO。 82 | */ 83 | +(BOOL) handleOpenURL:(NSURL *) url delegate:(id) delegate; 84 | 85 | 86 | 87 | /*! @brief 检查微信是否已被用户安装 88 | * 89 | * @return 微信已安装返回YES,未安装返回NO。 90 | */ 91 | +(BOOL) isWXAppInstalled; 92 | 93 | 94 | 95 | /*! @brief 判断当前微信的版本是否支持OpenApi 96 | * 97 | * @return 支持返回YES,不支持返回NO。 98 | */ 99 | +(BOOL) isWXAppSupportApi; 100 | 101 | 102 | 103 | /*! @brief 获取微信的itunes安装地址 104 | * 105 | * @return 微信的安装地址字符串。 106 | */ 107 | +(NSString *) getWXAppInstallUrl; 108 | 109 | 110 | 111 | /*! @brief 获取当前微信SDK的版本号 112 | * 113 | * @return 返回当前微信SDK的版本号 114 | */ 115 | +(NSString *) getApiVersion; 116 | 117 | 118 | 119 | /*! @brief 打开微信 120 | * 121 | * @return 成功返回YES,失败返回NO。 122 | */ 123 | +(BOOL) openWXApp; 124 | 125 | 126 | 127 | /*! @brief 发送请求到微信,等待微信返回onResp 128 | * 129 | * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持以下类型 130 | * SendAuthReq、SendMessageToWXReq、PayReq等。 131 | * @param req 具体的发送请求,在调用函数后,请自己释放。 132 | * @return 成功返回YES,失败返回NO。 133 | */ 134 | +(BOOL) sendReq:(BaseReq*)req; 135 | 136 | /*! @brief 发送Auth请求到微信,支持用户没安装微信,等待微信返回onResp 137 | * 138 | * 函数调用后,会切换到微信的界面。第三方应用程序等待微信返回onResp。微信在异步处理完成后一定会调用onResp。支持SendAuthReq类型。 139 | * @param req 具体的发送请求,在调用函数后,请自己释放。 140 | * @param viewController 当前界面对象。 141 | * @param delegate WXApiDelegate对象,用来接收微信触发的消息。 142 | * @return 成功返回YES,失败返回NO。 143 | */ 144 | +(BOOL) sendAuthReq:(SendAuthReq*) req viewController : (UIViewController*) viewController delegate:(id) delegate; 145 | 146 | 147 | /*! @brief 收到微信onReq的请求,发送对应的应答给微信,并切换到微信界面 148 | * 149 | * 函数调用后,会切换到微信的界面。第三方应用程序收到微信onReq的请求,异步处理该请求,完成后必须调用该函数。可能发送的相应有 150 | * GetMessageFromWXResp、ShowMessageFromWXResp等。 151 | * @param resp 具体的应答内容,调用函数后,请自己释放 152 | * @return 成功返回YES,失败返回NO。 153 | */ 154 | +(BOOL) sendResp:(BaseResp*)resp; 155 | 156 | 157 | @end 158 | -------------------------------------------------------------------------------- /src/ios/WXApiObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // MMApiObject.h 3 | // Api对象,包含所有接口和对象数据定义 4 | // 5 | // Created by Wechat on 12-2-28. 6 | // Copyright (c) 2012年 Tencent. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | /*! @brief 错误码 13 | * 14 | */ 15 | enum WXErrCode { 16 | WXSuccess = 0, /**< 成功 */ 17 | WXErrCodeCommon = -1, /**< 普通错误类型 */ 18 | WXErrCodeUserCancel = -2, /**< 用户点击取消并返回 */ 19 | WXErrCodeSentFail = -3, /**< 发送失败 */ 20 | WXErrCodeAuthDeny = -4, /**< 授权失败 */ 21 | WXErrCodeUnsupport = -5, /**< 微信不支持 */ 22 | }; 23 | 24 | 25 | 26 | /*! @brief 请求发送场景 27 | * 28 | */ 29 | enum WXScene { 30 | WXSceneSession = 0, /**< 聊天界面 */ 31 | WXSceneTimeline = 1, /**< 朋友圈 */ 32 | WXSceneFavorite = 2, /**< 收藏 */ 33 | }; 34 | 35 | 36 | 37 | enum WXAPISupport { 38 | WXAPISupportSession = 0, 39 | }; 40 | 41 | 42 | 43 | /*! @brief 跳转profile类型 44 | * 45 | */ 46 | enum WXBizProfileType{ 47 | WXBizProfileType_Normal = 0, //**< 普通公众号 */ 48 | WXBizProfileType_Device = 1, //**< 硬件公众号 */ 49 | }; 50 | 51 | 52 | 53 | /*! @brief 跳转mp网页类型 54 | * 55 | */ 56 | enum WXMPWebviewType { 57 | WXMPWebviewType_Ad = 0, /**< 广告网页 **/ 58 | }; 59 | 60 | #pragma mark - BaseReq 61 | /*! @brief 该类为微信终端SDK所有请求类的基类 62 | * 63 | */ 64 | @interface BaseReq : NSObject 65 | 66 | /** 请求类型 */ 67 | @property (nonatomic, assign) int type; 68 | /** 由用户微信号和AppID组成的唯一标识,发送请求时第三方程序必须填写,用于校验微信用户是否换号登录*/ 69 | @property (nonatomic, retain) NSString* openID; 70 | 71 | @end 72 | 73 | 74 | 75 | #pragma mark - BaseResp 76 | /*! @brief 该类为微信终端SDK所有响应类的基类 77 | * 78 | */ 79 | @interface BaseResp : NSObject 80 | /** 错误码 */ 81 | @property (nonatomic, assign) int errCode; 82 | /** 错误提示字符串 */ 83 | @property (nonatomic, retain) NSString *errStr; 84 | /** 响应类型 */ 85 | @property (nonatomic, assign) int type; 86 | 87 | @end 88 | 89 | 90 | 91 | #pragma mark - WXMediaMessage 92 | @class WXMediaMessage; 93 | 94 | /*! @brief 第三方向微信终端发起支付的消息结构体 95 | * 96 | * 第三方向微信终端发起支付的消息结构体,微信终端处理后会向第三方返回处理结果 97 | * @see PayResp 98 | */ 99 | @interface PayReq : BaseReq 100 | 101 | /** 商家向财付通申请的商家id */ 102 | @property (nonatomic, retain) NSString *partnerId; 103 | /** 预支付订单 */ 104 | @property (nonatomic, retain) NSString *prepayId; 105 | /** 随机串,防重发 */ 106 | @property (nonatomic, retain) NSString *nonceStr; 107 | /** 时间戳,防重发 */ 108 | @property (nonatomic, assign) UInt32 timeStamp; 109 | /** 商家根据财付通文档填写的数据和签名 */ 110 | @property (nonatomic, retain) NSString *package; 111 | /** 商家根据微信开放平台文档对数据做的签名 */ 112 | @property (nonatomic, retain) NSString *sign; 113 | 114 | @end 115 | 116 | 117 | 118 | #pragma mark - PayResp 119 | /*! @brief 微信终端返回给第三方的关于支付结果的结构体 120 | * 121 | * 微信终端返回给第三方的关于支付结果的结构体 122 | */ 123 | @interface PayResp : BaseResp 124 | 125 | /** 财付通返回给商家的信息 */ 126 | @property (nonatomic, retain) NSString *returnKey; 127 | 128 | @end 129 | 130 | 131 | #pragma mark - SendAuthReq 132 | /*! @brief 第三方程序向微信终端请求认证的消息结构 133 | * 134 | * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数, 135 | * 向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。 136 | * @see SendAuthResp 137 | */ 138 | @interface SendAuthReq : BaseReq 139 | /** 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。微信终端处理完后会向第三方程序发送一个处理结果。 140 | * @see SendAuthResp 141 | * @note scope字符串长度不能超过1K 142 | */ 143 | @property (nonatomic, retain) NSString* scope; 144 | /** 第三方程序本身用来标识其请求的唯一性,最后跳转回第三方程序时,由微信终端回传。 145 | * @note state字符串长度不能超过1K 146 | */ 147 | @property (nonatomic, retain) NSString* state; 148 | @end 149 | 150 | 151 | 152 | #pragma mark - SendAuthResp 153 | /*! @brief 微信处理完第三方程序的认证和权限申请后向第三方程序回送的处理结果。 154 | * 155 | * 第三方程序要向微信申请认证,并请求某些权限,需要调用WXApi的sendReq成员函数,向微信终端发送一个SendAuthReq消息结构。 156 | * 微信终端处理完后会向第三方程序发送一个SendAuthResp。 157 | * @see onResp 158 | */ 159 | @interface SendAuthResp : BaseResp 160 | @property (nonatomic, retain) NSString* code; 161 | /** 第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传 162 | * @note state字符串长度不能超过1K 163 | */ 164 | @property (nonatomic, retain) NSString* state; 165 | @property (nonatomic, retain) NSString* lang; 166 | @property (nonatomic, retain) NSString* country; 167 | @end 168 | 169 | 170 | 171 | #pragma mark - SendMessageToWXReq 172 | /*! @brief 第三方程序发送消息至微信终端程序的消息结构体 173 | * 174 | * 第三方程序向微信发送信息需要传入SendMessageToWXReq结构体,信息类型包括文本消息和多媒体消息, 175 | * 分别对应于text和message成员。调用该方法后,微信处理完信息会向第三方程序发送一个处理结果。 176 | * @see SendMessageToWXResp 177 | */ 178 | @interface SendMessageToWXReq : BaseReq 179 | /** 发送消息的文本内容 180 | * @note 文本长度必须大于0且小于10K 181 | */ 182 | @property (nonatomic, retain) NSString* text; 183 | /** 发送消息的多媒体内容 184 | * @see WXMediaMessage 185 | */ 186 | @property (nonatomic, retain) WXMediaMessage* message; 187 | /** 发送消息的类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */ 188 | @property (nonatomic, assign) BOOL bText; 189 | /** 发送的目标场景,可以选择发送到会话(WXSceneSession)或者朋友圈(WXSceneTimeline)。 默认发送到会话。 190 | * @see WXScene 191 | */ 192 | @property (nonatomic, assign) int scene; 193 | 194 | @end 195 | 196 | 197 | 198 | #pragma mark - SendMessageToWXResp 199 | /*! @brief 微信终端向第三方程序返回的SendMessageToWXReq处理结果。 200 | * 201 | * 第三方程序向微信终端发送SendMessageToWXReq后,微信发送回来的处理结果,该结果用SendMessageToWXResp表示。 202 | */ 203 | @interface SendMessageToWXResp : BaseResp 204 | @property(nonatomic, retain) NSString* lang; 205 | @property(nonatomic, retain) NSString* country; 206 | @end 207 | 208 | 209 | #pragma mark - GetMessageFromWXReq 210 | /*! @brief 微信终端向第三方程序请求提供内容的消息结构体。 211 | * 212 | * 微信终端向第三方程序请求提供内容,微信终端会向第三方程序发送GetMessageFromWXReq消息结构体, 213 | * 需要第三方程序调用sendResp返回一个GetMessageFromWXResp消息结构体。 214 | */ 215 | @interface GetMessageFromWXReq : BaseReq 216 | @property (nonatomic, retain) NSString* lang; 217 | @property (nonatomic, retain) NSString* country; 218 | @end 219 | 220 | 221 | 222 | #pragma mark - GetMessageFromWXResp 223 | /*! @brief 微信终端向第三方程序请求提供内容,第三方程序向微信终端返回的消息结构体。 224 | * 225 | * 微信终端向第三方程序请求提供内容,第三方程序调用sendResp向微信终端返回一个GetMessageFromWXResp消息结构体。 226 | */ 227 | @interface GetMessageFromWXResp : BaseResp 228 | /** 向微信终端提供的文本内容 229 | @note 文本长度必须大于0且小于10K 230 | */ 231 | @property (nonatomic, retain) NSString* text; 232 | /** 向微信终端提供的多媒体内容。 233 | * @see WXMediaMessage 234 | */ 235 | @property (nonatomic, retain) WXMediaMessage* message; 236 | /** 向微信终端提供内容的消息类型,包括文本消息和多媒体消息两种,两者只能选择其一,不能同时发送文本和多媒体消息 */ 237 | @property (nonatomic, assign) BOOL bText; 238 | @end 239 | 240 | 241 | 242 | #pragma mark - ShowMessageFromWXReq 243 | /*! @brief 微信通知第三方程序,要求第三方程序显示的消息结构体。 244 | * 245 | * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。 246 | * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。 247 | */ 248 | @interface ShowMessageFromWXReq : BaseReq 249 | /** 微信终端向第三方程序发送的要求第三方程序处理的多媒体内容 250 | * @see WXMediaMessage 251 | */ 252 | @property (nonatomic, retain) WXMediaMessage* message; 253 | @property (nonatomic, retain) NSString* lang; 254 | @property (nonatomic, retain) NSString* country; 255 | @end 256 | 257 | 258 | 259 | #pragma mark - ShowMessageFromWXResp 260 | /*! @brief 微信通知第三方程序,要求第三方程序显示或处理某些消息,第三方程序处理完后向微信终端发送的处理结果。 261 | * 262 | * 微信需要通知第三方程序显示或处理某些内容时,会向第三方程序发送ShowMessageFromWXReq消息结构体。 263 | * 第三方程序处理完内容后调用sendResp向微信终端发送ShowMessageFromWXResp。 264 | */ 265 | @interface ShowMessageFromWXResp : BaseResp 266 | @end 267 | 268 | 269 | 270 | #pragma mark - LaunchFromWXReq 271 | /*! @brief 微信终端打开第三方程序携带的消息结构体 272 | * 273 | * 微信向第三方发送的结构体,第三方不需要返回 274 | */ 275 | @interface LaunchFromWXReq : BaseReq 276 | @property (nonatomic, retain) WXMediaMessage* message; 277 | @property (nonatomic, retain) NSString* lang; 278 | @property (nonatomic, retain) NSString* country; 279 | @end 280 | 281 | #pragma mark - OpenTempSessionReq 282 | /* ! @brief 第三方通知微信,打开临时会话 283 | * 284 | * 第三方通知微信,打开临时会话 285 | */ 286 | @interface OpenTempSessionReq : BaseReq 287 | /** 需要打开的用户名 288 | * @attention 长度不能超过512字节 289 | */ 290 | @property (nonatomic, retain) NSString* username; 291 | /** 开发者自定义参数,拉起临时会话后会发给开发者后台,可以用于识别场景 292 | * @attention 长度不能超过32位 293 | */ 294 | @property (nonatomic, retain) NSString* sessionFrom; 295 | @end 296 | 297 | #pragma mark - OpenTempSessionResp 298 | /*! @brief 微信终端向第三方程序返回的OpenTempSessionReq处理结果。 299 | * 300 | * 第三方程序向微信终端发送OpenTempSessionReq后,微信发送回来的处理结果,该结果用OpenTempSessionResp表示。 301 | */ 302 | @interface OpenTempSessionResp : BaseResp 303 | 304 | @end 305 | 306 | #pragma mark - OpenWebviewReq 307 | /* ! @brief 第三方通知微信启动内部浏览器,打开指定网页 308 | * 309 | * 第三方通知微信启动内部浏览器,打开指定Url对应的网页 310 | */ 311 | @interface OpenWebviewReq : BaseReq 312 | /** 需要打开的网页对应的Url 313 | * @attention 长度不能超过1024 314 | */ 315 | @property(nonatomic,retain)NSString* url; 316 | 317 | @end 318 | 319 | #pragma mark - OpenWebviewResp 320 | /*! @brief 微信终端向第三方程序返回的OpenWebviewReq处理结果 321 | * 322 | * 第三方程序向微信终端发送OpenWebviewReq后,微信发送回来的处理结果,该结果用OpenWebviewResp表示 323 | */ 324 | @interface OpenWebviewResp : BaseResp 325 | 326 | @end 327 | 328 | #pragma mark - OpenRankListReq 329 | /* ! @brief 第三方通知微信,打开硬件排行榜 330 | * 331 | * 第三方通知微信,打开硬件排行榜 332 | */ 333 | @interface OpenRankListReq : BaseReq 334 | 335 | @end 336 | 337 | #pragma mark - OpenRanklistResp 338 | /*! @brief 微信终端向第三方程序返回的OpenRankListReq处理结果。 339 | * 340 | * 第三方程序向微信终端发送OpenRankListReq后,微信发送回来的处理结果,该结果用OpenRankListResp表示。 341 | */ 342 | @interface OpenRankListResp : BaseResp 343 | 344 | @end 345 | 346 | #pragma mark - JumpToBizProfileReq 347 | /* ! @brief 第三方通知微信,打开指定微信号profile页面 348 | * 349 | * 第三方通知微信,打开指定微信号profile页面 350 | */ 351 | @interface JumpToBizProfileReq : BaseReq 352 | /** 跳转到该公众号的profile 353 | * @attention 长度不能超过512字节 354 | */ 355 | @property (nonatomic, retain) NSString* username; 356 | /** 如果用户加了该公众号为好友,extMsg会上传到服务器 357 | * @attention 长度不能超过1024字节 358 | */ 359 | @property (nonatomic, retain) NSString* extMsg; 360 | /** 361 | * 跳转的公众号类型 362 | * @see WXBizProfileType 363 | */ 364 | @property (nonatomic, assign) int profileType; 365 | @end 366 | 367 | 368 | 369 | #pragma mark - JumpToBizWebviewReq 370 | /* ! @brief 第三方通知微信,打开指定usrname的profile网页版 371 | * 372 | */ 373 | @interface JumpToBizWebviewReq : BaseReq 374 | /** 跳转的网页类型,目前只支持广告页 375 | * @see WXMPWebviewType 376 | */ 377 | @property(nonatomic, assign) int webType; 378 | /** 跳转到该公众号的profile网页版 379 | * @attention 长度不能超过512字节 380 | */ 381 | @property(nonatomic, retain) NSString* tousrname; 382 | /** 如果用户加了该公众号为好友,extMsg会上传到服务器 383 | * @attention 长度不能超过1024字节 384 | */ 385 | @property(nonatomic, retain) NSString* extMsg; 386 | 387 | @end 388 | 389 | #pragma mark - WXCardItem 390 | 391 | @interface WXCardItem : NSObject 392 | /** 卡id 393 | * @attention 长度不能超过1024字节 394 | */ 395 | @property (nonatomic,retain) NSString* cardId; 396 | /** ext信息 397 | * @attention 长度不能超过2024字节 398 | * 具体见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.954-.E5.8D.A1.E5.88.B8.E6.89.A9.E5.B1.95.E5.AD.97.E6.AE.B5.E5.8F.8A.E7.AD.BE.E5.90.8D.E7.94.9F.E6.88.90.E7.AE.97.E6.B3.95 卡券扩展字段cardExt说明 399 | */ 400 | @property (nonatomic,retain) NSString* extMsg; 401 | /** 402 | * @attention 卡的状态,req不需要填。resp:0为未添加,1为已添加。 403 | */ 404 | @property (nonatomic,assign) UInt32 cardState; 405 | @end; 406 | 407 | #pragma mark - AddCardToWXCardPackageReq 408 | /* ! @brief 请求添加卡券至微信卡包 409 | * 410 | */ 411 | 412 | @interface AddCardToWXCardPackageReq : BaseReq 413 | /** 卡列表 414 | * @attention 个数不能超过40个 类型WXCardItem 415 | */ 416 | @property (nonatomic,retain) NSArray* cardAry; 417 | 418 | @end 419 | 420 | 421 | #pragma mark - AddCardToWXCardPackageResp 422 | /** ! @brief 微信返回第三方添加卡券结果 423 | * 424 | */ 425 | 426 | @interface AddCardToWXCardPackageResp : BaseResp 427 | /** 卡列表 428 | * @attention 个数不能超过40个 类型WXCardItem 429 | */ 430 | @property (nonatomic,retain) NSArray* cardAry; 431 | @end 432 | 433 | #pragma mark - WXMediaMessage 434 | 435 | /*! @brief 多媒体消息结构体 436 | * 437 | * 用于微信终端和第三方程序之间传递消息的多媒体消息内容 438 | */ 439 | @interface WXMediaMessage : NSObject 440 | 441 | +(WXMediaMessage *) message; 442 | 443 | /** 标题 444 | * @note 长度不能超过512字节 445 | */ 446 | @property (nonatomic, retain) NSString *title; 447 | /** 描述内容 448 | * @note 长度不能超过1K 449 | */ 450 | @property (nonatomic, retain) NSString *description; 451 | /** 缩略图数据 452 | * @note 大小不能超过32K 453 | */ 454 | @property (nonatomic, retain) NSData *thumbData; 455 | /** 456 | * @note 长度不能超过64字节 457 | */ 458 | @property (nonatomic, retain) NSString *mediaTagName; 459 | /** 460 | * 461 | */ 462 | @property (nonatomic, retain) NSString *messageExt; 463 | @property (nonatomic, retain) NSString *messageAction; 464 | /** 465 | * 多媒体数据对象,可以为WXImageObject,WXMusicObject,WXVideoObject,WXWebpageObject等。 466 | */ 467 | @property (nonatomic, retain) id mediaObject; 468 | 469 | /*! @brief 设置消息缩略图的方法 470 | * 471 | * @param image 缩略图 472 | * @note 大小不能超过32K 473 | */ 474 | - (void) setThumbImage:(UIImage *)image; 475 | 476 | @end 477 | 478 | 479 | 480 | #pragma mark - WXImageObject 481 | /*! @brief 多媒体消息中包含的图片数据对象 482 | * 483 | * 微信终端和第三方程序之间传递消息中包含的图片数据对象。 484 | * @note imageData和imageUrl成员不能同时为空 485 | * @see WXMediaMessage 486 | */ 487 | @interface WXImageObject : NSObject 488 | /*! @brief 返回一个WXImageObject对象 489 | * 490 | * @note 返回的WXImageObject对象是自动释放的 491 | */ 492 | +(WXImageObject *) object; 493 | 494 | /** 图片真实数据内容 495 | * @note 大小不能超过10M 496 | */ 497 | @property (nonatomic, retain) NSData *imageData; 498 | /** 图片url 499 | * @note 长度不能超过10K 500 | */ 501 | @property (nonatomic, retain) NSString *imageUrl; 502 | 503 | @end 504 | 505 | 506 | #pragma mark - WXMusicObject 507 | /*! @brief 多媒体消息中包含的音乐数据对象 508 | * 509 | * 微信终端和第三方程序之间传递消息中包含的音乐数据对象。 510 | * @note musicUrl和musicLowBandUrl成员不能同时为空。 511 | * @see WXMediaMessage 512 | */ 513 | @interface WXMusicObject : NSObject 514 | /*! @brief 返回一个WXMusicObject对象 515 | * 516 | * @note 返回的WXMusicObject对象是自动释放的 517 | */ 518 | +(WXMusicObject *) object; 519 | 520 | /** 音乐网页的url地址 521 | * @note 长度不能超过10K 522 | */ 523 | @property (nonatomic, retain) NSString *musicUrl; 524 | /** 音乐lowband网页的url地址 525 | * @note 长度不能超过10K 526 | */ 527 | @property (nonatomic, retain) NSString *musicLowBandUrl; 528 | /** 音乐数据url地址 529 | * @note 长度不能超过10K 530 | */ 531 | @property (nonatomic, retain) NSString *musicDataUrl; 532 | 533 | /**音乐lowband数据url地址 534 | * @note 长度不能超过10K 535 | */ 536 | @property (nonatomic, retain) NSString *musicLowBandDataUrl; 537 | 538 | @end 539 | 540 | 541 | 542 | #pragma mark - WXVideoObject 543 | /*! @brief 多媒体消息中包含的视频数据对象 544 | * 545 | * 微信终端和第三方程序之间传递消息中包含的视频数据对象。 546 | * @note videoUrl和videoLowBandUrl不能同时为空。 547 | * @see WXMediaMessage 548 | */ 549 | @interface WXVideoObject : NSObject 550 | /*! @brief 返回一个WXVideoObject对象 551 | * 552 | * @note 返回的WXVideoObject对象是自动释放的 553 | */ 554 | +(WXVideoObject *) object; 555 | 556 | /** 视频网页的url地址 557 | * @note 长度不能超过10K 558 | */ 559 | @property (nonatomic, retain) NSString *videoUrl; 560 | /** 视频lowband网页的url地址 561 | * @note 长度不能超过10K 562 | */ 563 | @property (nonatomic, retain) NSString *videoLowBandUrl; 564 | 565 | @end 566 | 567 | 568 | 569 | #pragma mark - WXWebpageObject 570 | /*! @brief 多媒体消息中包含的网页数据对象 571 | * 572 | * 微信终端和第三方程序之间传递消息中包含的网页数据对象。 573 | * @see WXMediaMessage 574 | */ 575 | @interface WXWebpageObject : NSObject 576 | /*! @brief 返回一个WXWebpageObject对象 577 | * 578 | * @note 返回的WXWebpageObject对象是自动释放的 579 | */ 580 | +(WXWebpageObject *) object; 581 | 582 | /** 网页的url地址 583 | * @note 不能为空且长度不能超过10K 584 | */ 585 | @property (nonatomic, retain) NSString *webpageUrl; 586 | 587 | @end 588 | 589 | 590 | 591 | #pragma mark - WXAppExtendObject 592 | /*! @brief 多媒体消息中包含的App扩展数据对象 593 | * 594 | * 第三方程序向微信终端发送包含WXAppExtendObject的多媒体消息, 595 | * 微信需要处理该消息时,会调用该第三方程序来处理多媒体消息内容。 596 | * @note url,extInfo和fileData不能同时为空 597 | * @see WXMediaMessage 598 | */ 599 | @interface WXAppExtendObject : NSObject 600 | /*! @brief 返回一个WXAppExtendObject对象 601 | * 602 | * @note 返回的WXAppExtendObject对象是自动释放的 603 | */ 604 | +(WXAppExtendObject *) object; 605 | 606 | /** 若第三方程序不存在,微信终端会打开该url所指的App下载地址 607 | * @note 长度不能超过10K 608 | */ 609 | @property (nonatomic, retain) NSString *url; 610 | /** 第三方程序自定义简单数据,微信终端会回传给第三方程序处理 611 | * @note 长度不能超过2K 612 | */ 613 | @property (nonatomic, retain) NSString *extInfo; 614 | /** App文件数据,该数据发送给微信好友,微信好友需要点击后下载数据,微信终端会回传给第三方程序处理 615 | * @note 大小不能超过10M 616 | */ 617 | @property (nonatomic, retain) NSData *fileData; 618 | 619 | @end 620 | 621 | 622 | 623 | #pragma mark - WXEmoticonObject 624 | /*! @brief 多媒体消息中包含的表情数据对象 625 | * 626 | * 微信终端和第三方程序之间传递消息中包含的表情数据对象。 627 | * @see WXMediaMessage 628 | */ 629 | @interface WXEmoticonObject : NSObject 630 | 631 | /*! @brief 返回一个WXEmoticonObject对象 632 | * 633 | * @note 返回的WXEmoticonObject对象是自动释放的 634 | */ 635 | +(WXEmoticonObject *) object; 636 | 637 | /** 表情真实数据内容 638 | * @note 大小不能超过10M 639 | */ 640 | @property (nonatomic, retain) NSData *emoticonData; 641 | 642 | @end 643 | 644 | 645 | 646 | #pragma mark - WXFileObject 647 | /*! @brief 多媒体消息中包含的文件数据对象 648 | * 649 | * @see WXMediaMessage 650 | */ 651 | @interface WXFileObject : NSObject 652 | 653 | /*! @brief 返回一个WXFileObject对象 654 | * 655 | * @note 返回的WXFileObject对象是自动释放的 656 | */ 657 | +(WXFileObject *) object; 658 | 659 | /** 文件后缀名 660 | * @note 长度不超过64字节 661 | */ 662 | @property (nonatomic, retain) NSString *fileExtension; 663 | 664 | /** 文件真实数据内容 665 | * @note 大小不能超过10M 666 | */ 667 | @property (nonatomic, retain) NSData *fileData; 668 | 669 | @end 670 | -------------------------------------------------------------------------------- /src/ios/libWeChatSDK.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vilicvane/cordova-plugin-wechat/3e81767d1099865cda3ba1dc57a38f8cac829f57/src/ios/libWeChatSDK.a -------------------------------------------------------------------------------- /src/wp/Google.ProtocolBuffersLite.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vilicvane/cordova-plugin-wechat/3e81767d1099865cda3ba1dc57a38f8cac829f57/src/wp/Google.ProtocolBuffersLite.dll -------------------------------------------------------------------------------- /src/wp/MicroMsgSDK.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vilicvane/cordova-plugin-wechat/3e81767d1099865cda3ba1dc57a38f8cac829f57/src/wp/MicroMsgSDK.dll -------------------------------------------------------------------------------- /src/wp/WeChat.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Cordova WeChat Plugin 3 | https://github.com/vilic/cordova-plugin-wechat 4 | 5 | by VILIC VANE 6 | https://github.com/vilic 7 | 8 | MIT License 9 | */ 10 | 11 | using MicroMsg.sdk; 12 | using System; 13 | using System.Windows.Navigation; 14 | using System.Runtime.Serialization; 15 | using WPCordovaClassLib.Cordova; 16 | using WPCordovaClassLib.Cordova.Commands; 17 | using WPCordovaClassLib.Cordova.JSON; 18 | using WPCordovaClassLib.CordovaLib; 19 | using Windows.Phone.Storage.SharedAccess; 20 | using Cordova.Extension.Commands; 21 | using System.Windows; 22 | using System.IO; 23 | using System.Linq; 24 | using System.Xml.Linq; 25 | using Microsoft.Phone.Shell; 26 | 27 | class WeChatAssociationUriMapper : UriMapperBase { 28 | UriMapperBase upper; 29 | 30 | public WeChatAssociationUriMapper(UriMapperBase upperMapper = null) { 31 | upper = upperMapper; 32 | } 33 | 34 | public override Uri MapUri(Uri uri) { 35 | string uriStr = uri.ToString(); 36 | 37 | if (uriStr.Contains("/FileTypeAssociation")) { 38 | int fileIDIndex = uriStr.IndexOf("fileToken=") + 10; 39 | string fileID = uriStr.Substring(fileIDIndex); 40 | string incommingFileName = SharedStorageAccessManager.GetSharedFileName(fileID); 41 | 42 | // Path.GetExtension will return String.Empty if no file extension found. 43 | int extensionIndex = incommingFileName.LastIndexOf('.') + 1; 44 | string incomingFileType = incommingFileName.Substring(extensionIndex).ToLower(); 45 | 46 | if (incomingFileType == WeChat.appId) { 47 | return new Uri("/WeChatCallbackPage.xaml?fileToken=" + fileID, UriKind.Relative); 48 | } 49 | } 50 | 51 | if (upper != null) { 52 | var upperResult = upper.MapUri(uri); 53 | 54 | if (upperResult != uri) { 55 | return upperResult; 56 | } 57 | } 58 | 59 | return new Uri("/MainPage.xaml", UriKind.Relative); 60 | } 61 | } 62 | 63 | namespace Cordova.Extension.Commands { 64 | [DataContract] 65 | enum WeChatShareType { 66 | [EnumMember] 67 | app = 1, 68 | [EnumMember] 69 | emotion, 70 | [EnumMember] 71 | file, 72 | [EnumMember] 73 | image, 74 | [EnumMember] 75 | music, 76 | [EnumMember] 77 | video, 78 | [EnumMember] 79 | webpage 80 | } 81 | 82 | [DataContract] 83 | enum WeChatScene { 84 | [EnumMember] 85 | chosenByUser, 86 | [EnumMember] 87 | session, 88 | [EnumMember] 89 | timeline 90 | } 91 | 92 | [DataContract] 93 | class WeChatMessageOptions { 94 | [DataMember] 95 | public WeChatShareType? type; 96 | [DataMember] 97 | public string title; 98 | [DataMember] 99 | public string description; 100 | //[DataMember] 101 | //public string mediaTagName; 102 | [DataMember] 103 | public string thumbData; 104 | [DataMember] 105 | public string url; 106 | [DataMember] 107 | public string data; 108 | } 109 | 110 | [DataContract] 111 | class WeChatShareOptions { 112 | [DataMember] 113 | public string text; 114 | [DataMember] 115 | public WeChatMessageOptions message; 116 | [DataMember] 117 | public WeChatScene? scene; 118 | } 119 | 120 | class WeChat : BaseCommand { 121 | public static string appId; 122 | static IWXAPI api; 123 | 124 | public static WeChat current = null; 125 | 126 | public const string WECHAT_APPID_KEY = "wechatappid"; 127 | public const string ERR_INVALID_OPTIONS = "ERR_INVALID_OPTIONS"; 128 | public const string ERR_UNSUPPORTED_MEDIA_TYPE = "ERR_UNSUPPORTED_MEDIA_TYPE"; 129 | public const string NO_RESULT = "NO_RESULT"; 130 | 131 | static WeChat() { 132 | var streamInfo = Application.GetResourceStream(new Uri("config.xml", UriKind.Relative)); 133 | 134 | var sr = new StreamReader(streamInfo.Stream); 135 | var document = XDocument.Parse(sr.ReadToEnd()); 136 | 137 | appId = (from results in document.Descendants() 138 | where results.Name.LocalName == "preference" && ((string)results.Attribute("name") == WECHAT_APPID_KEY) 139 | select (string)results.Attribute("value")).First(); 140 | 141 | api = WXAPIFactory.CreateWXAPI(appId); 142 | } 143 | 144 | public WeChat() { 145 | current = this; 146 | } 147 | 148 | public void share(string argsJSON) { 149 | var args = JsonHelper.Deserialize(argsJSON); 150 | var options = JsonHelper.Deserialize(args[0]); 151 | 152 | if (options == null) { 153 | dispatchResult(PluginResult.Status.JSON_EXCEPTION, ERR_INVALID_OPTIONS); 154 | return; 155 | } 156 | 157 | WXBaseMessage message = null; 158 | 159 | var messageOptions = options.message; 160 | 161 | if (messageOptions != null) { 162 | switch (messageOptions.type) { 163 | case WeChatShareType.app: 164 | break; 165 | case WeChatShareType.emotion: 166 | break; 167 | case WeChatShareType.file: 168 | break; 169 | case WeChatShareType.image: 170 | if (!String.IsNullOrEmpty(messageOptions.url)) { 171 | message = new WXImageMessage(messageOptions.url); 172 | } else if (!String.IsNullOrEmpty(messageOptions.data)) { 173 | message = new WXImageMessage(Convert.FromBase64String(messageOptions.data)); 174 | } else { 175 | dispatchResult(PluginResult.Status.ERROR, ERR_INVALID_OPTIONS); 176 | return; 177 | } 178 | break; 179 | case WeChatShareType.music: 180 | break; 181 | case WeChatShareType.video: 182 | break; 183 | case WeChatShareType.webpage: 184 | default: 185 | message = new WXWebpageMessage(messageOptions.url); 186 | break; 187 | } 188 | 189 | if (message == null) { 190 | dispatchResult(PluginResult.Status.ERROR, ERR_UNSUPPORTED_MEDIA_TYPE); 191 | return; 192 | } 193 | 194 | message.Title = messageOptions.title; 195 | message.Description = messageOptions.description; 196 | 197 | if (!String.IsNullOrEmpty(messageOptions.thumbData)) { 198 | message.ThumbData = Convert.FromBase64String(messageOptions.thumbData); 199 | } 200 | } else if (options.text != null) { 201 | message = new WXTextMessage(options.text); 202 | } else { 203 | dispatchResult(PluginResult.Status.ERROR, ERR_INVALID_OPTIONS); 204 | return; 205 | } 206 | 207 | var scene = options.scene; 208 | if (scene == null) { 209 | scene = WeChatScene.timeline; 210 | } 211 | 212 | try { 213 | var request = new SendMessageToWX.Req(message, (int)scene); 214 | api.SendReq(request); 215 | } catch (WXException e) { 216 | dispatchResult(PluginResult.Status.ERROR, e.Message); 217 | } 218 | } 219 | 220 | public void isInstalled(string argsJSON) { 221 | dispatchResult(PluginResult.Status.OK, true); 222 | } 223 | 224 | public void dispatchResult(PluginResult.Status status, object message) { 225 | DispatchCommandResult(new PluginResult(status, message)); 226 | } 227 | } 228 | 229 | } 230 | -------------------------------------------------------------------------------- /src/wp/WeChatCallbackPage.xaml: -------------------------------------------------------------------------------- 1 |  16 | 17 | -------------------------------------------------------------------------------- /src/wp/WeChatCallbackPage.xaml.cs: -------------------------------------------------------------------------------- 1 | /* 2 | Cordova WeChat Plugin 3 | https://github.com/vilic/cordova-plugin-wechat 4 | 5 | by VILIC VANE 6 | https://github.com/vilic 7 | 8 | MIT License 9 | */ 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using System.Linq; 14 | using System.Net; 15 | using System.Windows; 16 | using System.Windows.Controls; 17 | using System.Windows.Navigation; 18 | using Microsoft.Phone.Controls; 19 | using Microsoft.Phone.Shell; 20 | using MicroMsg.sdk; 21 | using Cordova.Extension.Commands; 22 | using WPCordovaClassLib.Cordova; 23 | 24 | namespace Cordova.Extension { 25 | public partial class WeChatCallbackPage : WXEntryBasePage { 26 | public WeChatCallbackPage() { 27 | InitializeComponent(); 28 | } 29 | 30 | public override void On_GetMessageFromWX_Request(GetMessageFromWX.Req request) { 31 | // not implemented 32 | goBack(); 33 | } 34 | 35 | public override void On_SendMessageToWX_Response(SendMessageToWX.Resp response) { 36 | goBack(); 37 | 38 | var status = response.ErrCode == 0 ? PluginResult.Status.OK : PluginResult.Status.ERROR; 39 | WeChat.current.dispatchResult(status, response.ErrStr); 40 | } 41 | 42 | public override void On_SendAuth_Response(SendAuth.Resp response) { 43 | // not implemented 44 | goBack(); 45 | } 46 | 47 | void goBack() { 48 | if (NavigationService.CanGoBack) { 49 | NavigationService.GoBack(); 50 | } else { 51 | NavigationService.Navigate(new Uri("/MainPage.xml", UriKind.Relative)); 52 | NavigationService.RemoveBackEntry(); 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /www/wechat.js: -------------------------------------------------------------------------------- 1 | /* 2 | Cordova WeChat Plugin 3 | https://github.com/vilic/cordova-plugin-wechat 4 | 5 | by VILIC VANE 6 | https://github.com/vilic 7 | 8 | MIT License 9 | */ 10 | 11 | exports.share = function (message, scene, onfulfilled, onrejected) { 12 | var text = null; 13 | 14 | if (typeof message == 'string') { 15 | text = message; 16 | message = null; 17 | } 18 | 19 | cordova 20 | .exec(function () { 21 | onfulfilled(); 22 | }, function (err) { 23 | onrejected(err); 24 | }, 'WeChat', 'share', [ 25 | { 26 | message: message, 27 | text: text, 28 | scene: scene 29 | } 30 | ]); 31 | }; 32 | 33 | exports.Scene = { 34 | chosenByUser: 0, 35 | session: 1, 36 | timeline: 2 37 | }; 38 | 39 | exports.ShareType = { 40 | app: 1, 41 | emotion: 2, 42 | file: 3, 43 | image: 4, 44 | music: 5, 45 | video: 6, 46 | webpage: 7 47 | }; 48 | 49 | exports.isInstalled = function (onfulfilled, onrejected) { 50 | cordova 51 | .exec(function (isInstalled) { 52 | onfulfilled(isInstalled); 53 | }, function (err) { 54 | onrejected(err); 55 | }, 'WeChat', 'isInstalled', []); 56 | }; 57 | --------------------------------------------------------------------------------