├── README.md ├── example ├── index.html ├── share-icon.jpg └── test.js └── src └── WeixinAPI.js /README.md: -------------------------------------------------------------------------------- 1 | WeixinAPI 2 | ========= 3 | 4 | Another Weixin WebView API 5 | 6 | ------------------- 7 | 8 | 微信API封装, finscn ( @大城小胖 ) 版. 9 | 10 | 参考了 的实现, 但做了非常大的改动,所以没有fork。 11 | 12 | 和 zxlie版本比 ,代码方面设计思路不同, 代码体积更小. 13 | 14 | 15 | 其他的详见代码注释 和 example 吧. 16 | 17 | 18 | ##### 已知bug 19 | 20 | 微信 5.4 Android版下, 分享到朋友圈时, 总是返回ok, 21 | 且返回两次.疑似微信android版本的bug. 22 | 23 | 建议在 shareTimeline 的 ready事件中做回调, 避免重复操作. 24 | 25 | 26 | ------------------- 27 | #### 简单示例: 28 | 29 | ``` 30 | 31 | var weixin = new WeixinAPI({ 32 | timeout: 2500, 33 | onReady: function() { 34 | $id("weixinState").innerHTML = "WeixinAPI is ready"; 35 | }, 36 | onTimeout: function() { 37 | $id("weixinState").innerHTML = "WeixinAPI is timeout"; 38 | } 39 | }); 40 | weixin.init(); 41 | 42 | 43 | 44 | var shareData = { 45 | title: "标题: 测试", 46 | desc: "描述: WeixinAPI 大城小胖 版 测试.", 47 | img_url: weixin.getAbsolutePath("share-icon.jpg") 48 | }; 49 | 50 | weixin.generalShare(shareData, { 51 | ready: function(shareData, action) { 52 | alert(action+" 操作 准备好了:" + shareData.title || shareData.desc); 53 | }, 54 | cancel: function(resp, action) { 55 | alert(action+" 操作 被取消 了." + resp.err_msg); 56 | }, 57 | succeed: function(resp, action) { 58 | alert(action+" 操作 成功 了." + resp.err_msg); 59 | }, 60 | fail: function(resp, action) { 61 | alert(action+" 操作 失败 了." + resp.err_msg); 62 | }, 63 | complate: function(resp, action) { 64 | alert(action+" 结束 了." + resp.err_msg); 65 | }, 66 | }); 67 | 68 | ``` -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Weixin Test 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 29 | 30 | 34 | 38 | 39 | 40 |
Loading...
41 |

42 | 43 |

44 |

45 | 46 | 47 |

48 |

49 | 50 | 51 |

52 |

53 | 54 |

55 |

56 | 57 |

58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /example/share-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/finscn/WeixinAPI/63f95311b9ae9f6bb1d49bcdfd556faa17e8366a/example/share-icon.jpg -------------------------------------------------------------------------------- /example/test.js: -------------------------------------------------------------------------------- 1 | 2 | var weixin = new WeixinAPI({ 3 | timeout: 2500, 4 | onReady: function() { 5 | $id("weixinState").innerHTML = "WeixinAPI is ready"; 6 | }, 7 | onTimeout: function() { 8 | $id("weixinState").innerHTML = "WeixinAPI is timeout"; 9 | } 10 | }); 11 | 12 | window.onload = function() { 13 | 14 | weixin.init(); 15 | 16 | var shareData = { 17 | title: "标题: 测试", 18 | desc: "描述: WeixinAPI 大城小胖 版 测试.", 19 | img_url: weixin.getAbsolutePath("share-icon.jpg") 20 | }; 21 | 22 | // 如果不想区分不同动作对应的数据和回调, 可以只使用 weixin.generalShare , 23 | // 然后在每个回调里面根据action参数自行判断对应动作 24 | /* 25 | 26 | weixin.generalShare(shareData, { 27 | ready: function(shareData, action) { 28 | alert(action+" 操作 准备好了:" + shareData.title || shareData.desc); 29 | }, 30 | cancel: function(resp, action) { 31 | alert(action+" 操作 被取消 了." + resp.err_msg); 32 | }, 33 | succeed: function(resp, action) { 34 | alert(action+" 操作 成功 了." + resp.err_msg); 35 | }, 36 | fail: function(resp, action) { 37 | alert(action+" 操作 失败 了." + resp.err_msg); 38 | }, 39 | complate: function(resp, action) { 40 | alert(action+" 结束 了." + resp.err_msg); 41 | }, 42 | }); 43 | 44 | */ 45 | 46 | weixin.shareToFriend(shareData, { 47 | ready: function(shareData, action) { 48 | alert("发送给朋友 操作 准备好了:" + shareData.title || shareData.desc); 49 | }, 50 | cancel: function(resp, action) { 51 | alert("发送给朋友 操作 被取消 了." + resp.err_msg); 52 | }, 53 | succeed: function(resp, action) { 54 | alert("发送给朋友 操作 成功 了." + resp.err_msg); 55 | }, 56 | fail: function(resp, action) { 57 | alert("发送给朋友 操作 失败 了." + resp.err_msg); 58 | }, 59 | complate: function(resp, action) { 60 | alert("发送给朋友 结束 了." + resp.err_msg); 61 | }, 62 | }); 63 | 64 | weixin.shareToTimeline(shareData, { 65 | ready: function(shareData, action) { 66 | alert("分享到朋友圈 操作 准备好了:" + shareData.title || shareData.desc); 67 | }, 68 | cancel: function(resp, action) { 69 | alert("分享到朋友圈 操作 被取消 了." + resp.err_msg); 70 | }, 71 | succeed: function(resp, action) { 72 | alert("分享到朋友圈 操作 成功 了." + resp.err_msg); 73 | }, 74 | fail: function(resp, action) { 75 | alert("分享到朋友圈 操作 失败 了." + resp.err_msg); 76 | }, 77 | complate: function(resp, action) { 78 | alert("分享到朋友圈 结束 了." + resp.err_msg); 79 | }, 80 | }); 81 | weixin.shareToWeibo(shareData, { 82 | ready: function(shareData, action) { 83 | alert("分享到腾讯微博 操作 准备好了:" + shareData.title || shareData.desc); 84 | }, 85 | cancel: function(resp, action) { 86 | alert("分享到腾讯微博 操作 被取消 了." + resp.err_msg); 87 | }, 88 | succeed: function(resp, action) { 89 | alert("分享到腾讯微博 操作 成功 了." + resp.err_msg); 90 | }, 91 | fail: function(resp, action) { 92 | alert("分享到腾讯微博 操作 失败 了." + resp.err_msg); 93 | }, 94 | complate: function(resp, action) { 95 | alert("分享到腾讯微博 结束 了." + resp.err_msg); 96 | }, 97 | }); 98 | 99 | initButtons(); 100 | }; 101 | 102 | function $id(id) { 103 | return document.getElementById(id); 104 | } 105 | 106 | function initButtons() { 107 | $id('getNetworkType').addEventListener('click', function() { 108 | weixin.getNetworkType(function(type) { 109 | $id('networkType').innerHTML = type; 110 | }); 111 | }); 112 | $id('showOptionMenu').addEventListener('click', function() { 113 | weixin.showOptionMenu(); 114 | }); 115 | $id('hideOptionMenu').addEventListener('click', function() { 116 | weixin.hideOptionMenu(); 117 | }); 118 | $id('showToolbar').addEventListener('click', function() { 119 | weixin.showToolbar(); 120 | }); 121 | $id('hideToolbar').addEventListener('click', function() { 122 | weixin.hideToolbar(); 123 | }); 124 | $id('closeWindow').addEventListener('click', function() { 125 | weixin.closeWindow(); 126 | }); 127 | 128 | $id('previewImages').addEventListener('click', function() { 129 | var picList = [ 130 | "http://content.52pk.com/files/121122/1284656_175821_1_lit.jpg", 131 | "http://www.520bizhi.com/uploads/allimg/1009/1-1009140646300-L.jpg", 132 | "http://himg2.huanqiu.com/attachment2010/110223/c929b22ce3.jpg", "http://p3.gexing.com/kongjianpifu/20121216/1544/50cd7be750bcf.jpg", 133 | "http://img.973.com/newspic/7db/7db758a2215a803fad99f586ae7c9787.jpg", 134 | "http://pic9.nipic.com/20100908/1304280_110709063517_2.jpg", 135 | "http://ww3.sinaimg.cn/large/a8a2249djw1dxcnox2sirj.jpg", 136 | "http://pic6.nipic.com/20100408/3017209_004258840970_2.jpg" 137 | ]; 138 | weixin.previewImages(picList[2], picList); 139 | }); 140 | 141 | 142 | } 143 | -------------------------------------------------------------------------------- /src/WeixinAPI.js: -------------------------------------------------------------------------------- 1 | /** 2 | 微信API封装, finscn ( @大城小胖 ) 版. 3 | 参考了 https://github.com/zxlie/WeixinApi 4 | 感谢原作者. 5 | **/ 6 | 7 | var WeixinAPI = function(options) { 8 | for (var p in options) { 9 | this[p] = options[p]; 10 | } 11 | }; 12 | 13 | WeixinAPI.isInWeixin = function() { 14 | return /MicroMessenger/i.test(navigator.userAgent); 15 | }; 16 | 17 | WeixinAPI.prototype = { 18 | constructor: WeixinAPI, 19 | 20 | //是否初始化完毕 21 | isReady: false, 22 | 23 | //超时时间, 如果超时后 isReady仍然为false, 通常表示不在微信的环境里. 24 | timeout: 2000, 25 | 26 | // 微信分享数据的基础模板, 通常不需要修改 27 | _shareDataTemplate: { 28 | "link": window.top.location.href, 29 | "img_width": "256", 30 | "img_height": "256", 31 | "img_url": undefined, 32 | "appid": undefined, 33 | "title": undefined, 34 | "desc": undefined 35 | }, 36 | 37 | // 基本微信分享数据, 会与实际设置的数据进行merge 38 | baseShareData: null, 39 | 40 | // shareReady 时的后续动作是否是异步的 41 | asyncShareReady: false, 42 | 43 | // 初始化方法, 用户需要主动调用. init之后才能进行其他操作.不要问我为什么不在构造函数里主动调用 :P 44 | init: function() { 45 | var Me = this; 46 | this.dataHolder = {}; 47 | this.callbackHolder = {}; 48 | 49 | this.baseShareData = this.baseShareData || {}; 50 | for (var p in this._shareDataTemplate) { 51 | this.baseShareData[p] = this._shareDataTemplate[p]; 52 | } 53 | 54 | var callback = function() { 55 | Me._initShareListeners(); 56 | Me.isReady = true; 57 | Me.onReady(); 58 | }; 59 | if (typeof WeixinJSBridge == "undefined") { 60 | document.addEventListener("WeixinJSBridgeReady", callback, false); 61 | setTimeout(function() { 62 | if (typeof WeixinJSBridge == "undefined") { 63 | Me.onTimeout(); 64 | } 65 | }, this.timeout); 66 | } else { 67 | callback(); 68 | } 69 | 70 | }, 71 | 72 | // WeixinJSBridge 初始化完毕后的回调 73 | onReady: function() {}, 74 | 75 | // WeixinJSBridge 初始化超时的回调,此时通常意味着不在微信环境. 76 | onTimeout: function() {}, 77 | 78 | 79 | /*********************************************/ 80 | /********* 分享相关内部函数, "_" 开头的用户无需关心 *********/ 81 | /*********************************************/ 82 | 83 | _initShareListeners: function() { 84 | var Me = this; 85 | // iOS微信5.4开始,只支持 general share 86 | WeixinJSBridge.on("menu:general:share", function(general) { 87 | Me._invokeGeneral("generalShare", general); 88 | }); 89 | // 以下3个事件只在微信5.4之前版本以及部分Android版本可用 90 | WeixinJSBridge.on("menu:share:appmessage", function() { 91 | Me._invoke("sendAppMessage"); 92 | }); 93 | WeixinJSBridge.on("menu:share:timeline", function() { 94 | Me._invoke("shareTimeline"); 95 | }); 96 | WeixinJSBridge.on("menu:share:weibo", function() { 97 | Me._invoke("shareWeibo"); 98 | }); 99 | }, 100 | 101 | _invokeCallBack: function(action, resp, callback) { 102 | var msg = resp["err_msg"]; 103 | var type; 104 | if (/:cancel$/.test(msg)) { 105 | type = "cancel"; 106 | } else if (/:ok$/.test(msg)) { 107 | type = "succeed"; 108 | } else if (/:fail$/.test(msg)) { 109 | type = "fail"; 110 | } 111 | if (callback) { 112 | if (typeof callback == "function") { 113 | callback(resp, action, type); 114 | } else { 115 | callback[type] && callback[type](resp, action, type); 116 | } 117 | callback["complete"] && callback["complete"](resp, action, "complete"); 118 | } 119 | }, 120 | 121 | 122 | _invoke: function(action) { 123 | 124 | var data = this.mergerData(this.dataHolder[action]); 125 | if (action == "shareTimeline") { 126 | var title = data["title"] || data["desc"]; 127 | data["title"] = data["desc"] || title; 128 | data["desc"] = title; 129 | } 130 | var callback = this.callbackHolder[action]; 131 | var readyCallback = callback ? callback["ready"] : null; 132 | 133 | var Me = this; 134 | 135 | // 微信 5.4 Android版下, 分享到朋友圈时, 总是返回ok, 136 | // 且返回两次.疑似微信android版本的bug. 137 | // 建议在 shareTimeline 的 ready事件中做回调, 避免重复操作. 138 | 139 | var doShare = function() { 140 | WeixinJSBridge.invoke(action, data, function(resp) { 141 | Me._invokeCallBack(action, resp, callback); 142 | }); 143 | }; 144 | 145 | if (this.asyncShareReady && readyCallback) { 146 | readyCallback(data, action, doShare); 147 | } else { 148 | if (!readyCallback || readyCallback(data, action, null) !== false) { 149 | doShare(); 150 | } 151 | } 152 | 153 | }, 154 | 155 | _invokeGeneral: function(action, wxGeneral) { 156 | // this.dataHolder[action] 157 | // general.generalShare 158 | var shareTo = wxGeneral.shareTo; 159 | switch (shareTo) { 160 | case "friend": 161 | case "appmessage": 162 | case "sendappmessage": 163 | shareTo = "friend"; 164 | action = "sendAppMessage"; 165 | break; 166 | case "timeline": 167 | shareTo = "timeline"; 168 | action = "shareTimeline"; 169 | break; 170 | case "weibo": 171 | shareTo = "weibo"; 172 | action = "shareWeibo"; 173 | break; 174 | } 175 | 176 | var data = this.mergerData(this.dataHolder[action]); 177 | if (action == "shareTimeline") { 178 | var title = data["title"] || data["desc"]; 179 | data["title"] = data["desc"] || title; 180 | data["desc"] = title; 181 | } 182 | var callback = this.callbackHolder[action]; 183 | var readyCallback = callback ? callback["ready"] : null; 184 | 185 | var Me = this; 186 | 187 | var doShare = function() { 188 | wxGeneral.generalShare(data, function(resp) { 189 | Me._invokeCallBack(action, resp, callback); 190 | }); 191 | }; 192 | 193 | if (this.asyncShareReady && readyCallback) { 194 | readyCallback(data, action, doShare); 195 | } else { 196 | readyCallback && readyCallback(data, action, null); 197 | doShare(); 198 | } 199 | }, 200 | 201 | /* 202 | 以下4个函数的参数说明: 203 | data: 微信所需要的分享时的数据 204 | callback: 分享的回调函数. 如果callback为一个函数,则此函数为分享后续操作的通用回调函数. 205 | 即,无论回调成功/失败/取消都会调用该函数. 206 | 参数为 resp, action, type 207 | resp: 微信返回的原始数据. 208 | action: 分享的动作 209 | type: 分享操作回调事件的类型: succeed,fail,cancel 210 | 211 | 如果callback为如下格式, 则相当于分别指定相应回调: 212 | { 213 | succeed: function(resp, action, type){}, // 分享成功 214 | fail: function(resp, action, type){}, // 分享失败 215 | cancel: function(resp, action, type){}, // 分享取消 216 | complete: function(resp, action, type){}, //通用回调函数 217 | 218 | ready: function(data, action){}, // 同步分享准备就绪 219 | 220 | ready: function(data, action, doShare){}, // 异步分享准备就绪 221 | //异步时, 需要在 ready里主动调用 doShare函数. 222 | } 223 | */ 224 | 225 | // 设置 所有分享操作 所使用的数据, 以及回调函数. 若要移除, 设置为null 226 | generalShare: function(data, callback) { 227 | this.shareToFriend(data, callback); 228 | this.shareToTimeline(data, callback); 229 | this.shareToWeibo(data, callback); 230 | }, 231 | 232 | // 设置 分享给朋友 时所使用的数据, 以及回调函数. 若要移除, 设置为null 233 | shareToFriend: function(data, callback) { 234 | this.dataHolder["sendAppMessage"] = data; 235 | this.callbackHolder["sendAppMessage"] = callback; 236 | }, 237 | 238 | // 设置 分享到朋友圈 时所使用的数据, 以及回调函数. 若要移除, 设置为null 239 | shareToTimeline: function(data, callback) { 240 | this.dataHolder["shareTimeline"] = data; 241 | this.callbackHolder["shareTimeline"] = callback; 242 | }, 243 | 244 | // 设置 分享到腾讯微博 时所使用的数据, 以及回调函数. 若要移除, 设置为null 245 | shareToWeibo: function(data, callback) { 246 | this.dataHolder["shareWeibo"] = data; 247 | this.callbackHolder["shareWeibo"] = callback; 248 | }, 249 | 250 | /*******************************/ 251 | /********* 其他功能函数 *********/ 252 | /*******************************/ 253 | 254 | previewImages: function(curSrc, srcList) { 255 | if (!curSrc || !srcList || srcList.length == 0) { 256 | return; 257 | } 258 | WeixinJSBridge.invoke("imagePreview", { 259 | "current": curSrc, 260 | "urls": srcList 261 | }); 262 | }, 263 | 264 | getNetworkType: function(callback) { 265 | if (callback && typeof callback == "function") { 266 | WeixinJSBridge.invoke("getNetworkType", {}, function(resp) { 267 | var type = resp["err_msg"]; 268 | // network_type:wifi wifi 269 | // network_type:edge edge 270 | // network_type:wwan 2G/3G 271 | // network_type:fail 网络断开 272 | var idx = 0; 273 | var preix = "network_type:"; 274 | if (type && type.indexOf(preix) == 0) { 275 | type = type.substring(preix.length); 276 | } 277 | callback(type); 278 | }); 279 | } 280 | }, 281 | 282 | callWeixin: function(cmd) { 283 | WeixinJSBridge.call(cmd); 284 | }, 285 | 286 | showOptionMenu: function() { 287 | WeixinJSBridge.call("showOptionMenu"); 288 | }, 289 | 290 | hideOptionMenu: function() { 291 | WeixinJSBridge.call("hideOptionMenu"); 292 | }, 293 | 294 | showToolbar: function() { 295 | WeixinJSBridge.call("showToolbar"); 296 | }, 297 | 298 | hideToolbar: function() { 299 | WeixinJSBridge.call("hideToolbar"); 300 | }, 301 | 302 | closeWindow: function() { 303 | WeixinJSBridge.call("closeWindow"); 304 | }, 305 | 306 | mergerData: function(data) { 307 | if (!data) { 308 | return data; 309 | } 310 | var _data = JSON.parse(JSON.stringify(this.baseShareData)); 311 | for (var p in data) { 312 | _data[p] = data[p]; 313 | } 314 | _data["title"] === undefined && (_data["title"] = _data["desc"]); 315 | _data["desc"] === undefined && (_data["desc"] = _data["title"]); 316 | return _data; 317 | }, 318 | 319 | // 将相对路径变为绝对路径 320 | getAbsolutePath: function(relativePath) { 321 | var img = new Image(); 322 | img.src = relativePath; 323 | var absolute = img.src; 324 | return absolute; 325 | } 326 | 327 | }; 328 | --------------------------------------------------------------------------------