微信JS-SDK 示例
1、html部分
1 <!DOCTYPE html>
2 <!-- saved from url=(0028){sh:$selfUrl} -->
3 <html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
4 <meta charset="utf-8">
5 <title>微信JS-SDK Demo</title>
6 <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
7 <link rel="stylesheet" href="{sh::RES}/jssdk/css/style.css">
8 </head>
9 <body ontouchstart="">
10 <div class="wxapi_container">
11 <div class="wxapi_index_container">
12 <ul class="label_box lbox_close wxapi_index_list">
13 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-basic">基础接口</a></li>
14 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-share">分享接口</a></li>
15 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-image">图像接口</a></li>
16 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-voice">音频接口</a></li>
17 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-smart">智能接口</a></li>
18 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-device">设备信息接口</a></li>
19 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-location">地理位置接口</a></li>
20 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-webview">界面操作接口</a></li>
21 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-scan">微信扫一扫接口</a></li>
22 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-shopping">微信小店接口</a></li>
23 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-card">微信卡券接口</a></li>
24 <li class="label_item wxapi_index_item"><a class="label_inner" href="{sh:$selfUrl}#menu-pay">微信支付接口</a></li>
25 </ul>
26 </div>
27 <div class="lbox_close wxapi_form">
28 <h3 id="menu-basic">基础接口</h3>
29 <span class="desc">判断当前客户端是否支持指定JS接口</span>
30 <button class="btn btn_primary" id="checkJsApi">checkJsApi</button>
31
32 <h3 id="menu-share">分享接口</h3>
33 <span class="desc">获取“分享到朋友圈”按钮点击状态及自定义分享内容接口</span>
34 <button class="btn btn_primary" id="onMenuShareTimeline">onMenuShareTimeline</button>
35 <span class="desc">获取“分享给朋友”按钮点击状态及自定义分享内容接口</span>
36 <button class="btn btn_primary" id="onMenuShareAppMessage">onMenuShareAppMessage</button>
37 <span class="desc">获取“分享到QQ”按钮点击状态及自定义分享内容接口</span>
38 <button class="btn btn_primary" id="onMenuShareQQ">onMenuShareQQ</button>
39 <span class="desc">获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口</span>
40 <button class="btn btn_primary" id="onMenuShareWeibo">onMenuShareWeibo</button>
41 <span class="desc">获取“分享到QZone”按钮点击状态及自定义分享内容接口</span>
42 <button class="btn btn_primary" id="onMenuShareQZone">onMenuShareQZone</button>
43
44 <h3 id="menu-image">图像接口</h3>
45 <span class="desc">拍照或从手机相册中选图接口</span>
46 <button class="btn btn_primary" id="chooseImage">chooseImage</button>
47 <span class="desc">预览图片接口</span>
48 <button class="btn btn_primary" id="previewImage">previewImage</button>
49 <span class="desc">上传图片接口</span>
50 <button class="btn btn_primary" id="uploadImage">uploadImage</button>
51 <span class="desc">下载图片接口</span>
52 <button class="btn btn_primary" id="downloadImage">downloadImage</button>
53
54 <h3 id="menu-voice">音频接口</h3>
55 <span class="desc">开始录音接口</span>
56 <button class="btn btn_primary" id="startRecord">startRecord</button>
57 <span class="desc">停止录音接口</span>
58 <button class="btn btn_primary" id="stopRecord">stopRecord</button>
59 <span class="desc">播放语音接口</span>
60 <button class="btn btn_primary" id="playVoice">playVoice</button>
61 <span class="desc">暂停播放接口</span>
62 <button class="btn btn_primary" id="pauseVoice">pauseVoice</button>
63 <span class="desc">停止播放接口</span>
64 <button class="btn btn_primary" id="stopVoice">stopVoice</button>
65 <span class="desc">上传语音接口</span>
66 <button class="btn btn_primary" id="uploadVoice">uploadVoice</button>
67 <span class="desc">下载语音接口</span>
68 <button class="btn btn_primary" id="downloadVoice">downloadVoice</button>
69
70 <h3 id="menu-smart">智能接口</h3>
71 <span class="desc">识别音频并返回识别结果接口</span>
72 <button class="btn btn_primary" id="translateVoice">translateVoice</button>
73
74 <h3 id="menu-device">设备信息接口</h3>
75 <span class="desc">获取网络状态接口</span>
76 <button class="btn btn_primary" id="getNetworkType">getNetworkType</button>
77
78 <h3 id="menu-location">地理位置接口</h3>
79 <span class="desc">使用微信内置地图查看位置接口</span>
80 <button class="btn btn_primary" id="openLocation">openLocation</button>
81 <span class="desc">获取地理位置接口</span>
82 <button class="btn btn_primary" id="getLocation">getLocation</button>
83
84 <h3 id="menu-webview">界面操作接口</h3>
85 <span class="desc">隐藏右上角菜单接口</span>
86 <button class="btn btn_primary" id="hideOptionMenu">hideOptionMenu</button>
87 <span class="desc">显示右上角菜单接口</span>
88 <button class="btn btn_primary" id="showOptionMenu">showOptionMenu</button>
89 <span class="desc">关闭当前网页窗口接口</span>
90 <button class="btn btn_primary" id="closeWindow">closeWindow</button>
91 <span class="desc">批量隐藏功能按钮接口</span>
92 <button class="btn btn_primary" id="hideMenuItems">hideMenuItems</button>
93 <span class="desc">批量显示功能按钮接口</span>
94 <button class="btn btn_primary" id="showMenuItems">showMenuItems</button>
95 <span class="desc">隐藏所有非基础按钮接口</span>
96 <button class="btn btn_primary" id="hideAllNonBaseMenuItem">hideAllNonBaseMenuItem</button>
97 <span class="desc">显示所有功能按钮接口</span>
98 <button class="btn btn_primary" id="showAllNonBaseMenuItem">showAllNonBaseMenuItem</button>
99
100 <h3 id="menu-scan">微信扫一扫</h3>
101 <span class="desc">调起微信扫一扫接口</span>
102 <button class="btn btn_primary" id="scanQRCode0">scanQRCode(微信处理结果)</button>
103 <button class="btn btn_primary" id="scanQRCode1">scanQRCode(直接返回结果)</button>
104
105 <h3 id="menu-shopping">微信小店接口</h3>
106 <span class="desc">跳转微信商品页接口</span>
107 <button class="btn btn_primary" id="openProductSpecificView">openProductSpecificView</button>
108
109 <h3 id="menu-card">微信卡券接口</h3>
110 <span class="desc">批量添加卡券接口</span>
111 <button class="btn btn_primary" id="addCard">addCard</button>
112 <span class="desc">调起适用于门店的卡券列表并获取用户选择列表</span>
113 <button class="btn btn_primary" id="chooseCard">chooseCard</button>
114 <span class="desc">查看微信卡包中的卡券接口</span>
115 <button class="btn btn_primary" id="openCard">openCard</button>
116
117 <h3 id="menu-pay">微信支付接口</h3>
118 <span class="desc">发起一个微信支付请求</span>
119 <button class="btn btn_primary" id="chooseWXPay">chooseWXPay</button>
120 </div>
121 </div>
122
123 <script src="{sh::RES}/jssdk/js/jweixin-1.0.0.js"></script>
124
125
126
127 <!-- 获取签名的核心 begin -->
128 <?php
129 import("@.ORG.jssdk");
130 $jssdk = new JSSDK(C('oauth_config.appid'), C('oauth_config.appsecret'));
131 $signPackage = $jssdk->GetSignPackage();
132 ?>
133 <!-- 获取签名的核心 end -->
134 <script>
135 /*
136 * 注意:
137 * 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
138 * 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。
139 * 3. 常见问题及完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
140 *
141 * 开发中遇到问题详见文档“附录5-常见错误及解决办法”解决,如仍未能解决可通过以下渠道反馈:
142 * 邮箱地址:weixin-open@qq.com
143 * 邮件主题:【微信JS-SDK反馈】具体问题
144 * 邮件内容说明:用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。
145 */
146 wx.config({
147 debug: false,
148 appId: '<?php echo $signPackage["appId"];?>',
149 timestamp: <?php echo $signPackage["timestamp"];?>,
150 nonceStr: '<?php echo $signPackage["nonceStr"];?>',
151 signature: '<?php echo $signPackage["signature"];?>',
152 jsApiList: [
153 'checkJsApi',
154 'onMenuShareTimeline',
155 'onMenuShareAppMessage',
156 'onMenuShareQQ',
157 'onMenuShareWeibo',
158 'onMenuShareQZone',
159 'hideMenuItems',
160 'showMenuItems',
161 'hideAllNonBaseMenuItem',
162 'showAllNonBaseMenuItem',
163 'translateVoice',
164 'startRecord',
165 'stopRecord',
166 'onVoiceRecordEnd',
167 'playVoice',
168 'onVoicePlayEnd',
169 'pauseVoice',
170 'stopVoice',
171 'uploadVoice',
172 'downloadVoice',
173 'chooseImage',
174 'previewImage',
175 'uploadImage',
176 'downloadImage',
177 'getNetworkType',
178 'openLocation',
179 'getLocation',
180 'hideOptionMenu',
181 'showOptionMenu',
182 'closeWindow',
183 'scanQRCode',
184 'chooseWXPay',
185 'openProductSpecificView',
186 'addCard',
187 'chooseCard',
188 'openCard'
189 ]
190 });
191 </script>
192 <script src="{sh::RES}/jssdk/js/zepto.min.js"></script>
193 <script src="{sh::RES}/jssdk/js/demo.js"> </script>
194
195 <div id="cli_dialog_div"></div></body></html>
2、js部分
1 /*
2 * 注意:
3 * 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
4 * 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。
5 * 3. 完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
6 *
7 * 如有问题请通过以下渠道反馈:
8 * 邮箱地址:weixin-open@qq.com
9 * 邮件主题:【微信JS-SDK反馈】具体问题
10 * 邮件内容说明:用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。
11 */
12 wx.ready(function () {
13 // 1 判断当前版本是否支持指定 JS 接口,支持批量判断
14 document.querySelector('#checkJsApi').onclick = function () {
15 wx.checkJsApi({
16 jsApiList: [
17 'getNetworkType',
18 'previewImage'
19 ],
20 success: function (res) {
21 alert(JSON.stringify(res));
22 }
23 });
24 };
25
26 // 2. 分享接口
27 // 2.1 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口
28 document.querySelector('#onMenuShareAppMessage').onclick = function () {
29 wx.onMenuShareAppMessage({
30 title: '互联网之子',
31 desc: '在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。',
32 link: 'http://movie.douban.com/subject/25785114/',
33 imgUrl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',
34 trigger: function (res) {
35 // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
36 alert('用户点击发送给朋友');
37 },
38 success: function (res) {
39 alert('已分享');
40 },
41 cancel: function (res) {
42 alert('已取消');
43 },
44 fail: function (res) {
45 alert(JSON.stringify(res));
46 }
47 });
48 alert('已注册获取“发送给朋友”状态事件');
49 };
50
51 // 2.2 监听“分享到朋友圈”按钮点击、自定义分享内容及分享结果接口
52 document.querySelector('#onMenuShareTimeline').onclick = function () {
53 wx.onMenuShareTimeline({
54 title: '互联网之子',
55 link: 'http://movie.douban.com/subject/25785114/',
56 imgUrl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',
57 trigger: function (res) {
58 // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
59 alert('用户点击分享到朋友圈');
60 },
61 success: function (res) {
62 alert('已分享');
63 },
64 cancel: function (res) {
65 alert('已取消');
66 },
67 fail: function (res) {
68 alert(JSON.stringify(res));
69 }
70 });
71 alert('已注册获取“分享到朋友圈”状态事件');
72 };
73
74 // 2.3 监听“分享到QQ”按钮点击、自定义分享内容及分享结果接口
75 document.querySelector('#onMenuShareQQ').onclick = function () {
76 wx.onMenuShareQQ({
77 title: '互联网之子',
78 desc: '在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。',
79 link: 'http://movie.douban.com/subject/25785114/',
80 imgUrl: 'http://img3.douban.com/view/movie_poster_cover/spst/public/p2166127561.jpg',
81 trigger: function (res) {
82 alert('用户点击分享到QQ');
83 },
84 complete: function (res) {
85 alert(JSON.stringify(res));
86 },
87 success: function (res) {
88 alert('已分享');
89 },
90 cancel: function (res) {
91 alert('已取消');
92 },
93 fail: function (res) {
94 alert(JSON.stringify(res));
95 }
96 });
97 alert('已注册获取“分享到 QQ”状态事件');
98 };
99
100 // 2.4 监听“分享到微博”按钮点击、自定义分享内容及分享结果接口
101 document.querySelector('#onMenuShareWeibo').onclick = function () {
102 wx.onMenuShareWeibo({
103 title: '互联网之子',
104 desc: '在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。',
105 link: 'http://movie.douban.com/subject/25785114/',
106 imgUrl: 'http://img3.douban.com/view/movie_poster_cover/spst/public/p2166127561.jpg',
107 trigger: function (res) {
108 alert('用户点击分享到微博');
109 },
110 complete: function (res) {
111 alert(JSON.stringify(res));
112 },
113 success: function (res) {
114 alert('已分享');
115 },
116 cancel: function (res) {
117 alert('已取消');
118 },
119 fail: function (res) {
120 alert(JSON.stringify(res));
121 }
122 });
123 alert('已注册获取“分享到微博”状态事件');
124 };
125
126 // 2.5 监听“分享到QZone”按钮点击、自定义分享内容及分享接口
127 document.querySelector('#onMenuShareQZone').onclick = function () {
128 wx.onMenuShareQZone({
129 title: '互联网之子',
130 desc: '在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。',
131 link: 'http://movie.douban.com/subject/25785114/',
132 imgUrl: 'http://img3.douban.com/view/movie_poster_cover/spst/public/p2166127561.jpg',
133 trigger: function (res) {
134 alert('用户点击分享到QZone');
135 },
136 complete: function (res) {
137 alert(JSON.stringify(res));
138 },
139 success: function (res) {
140 alert('已分享');
141 },
142 cancel: function (res) {
143 alert('已取消');
144 },
145 fail: function (res) {
146 alert(JSON.stringify(res));
147 }
148 });
149 alert('已注册获取“分享到QZone”状态事件');
150 };
151
152
153 // 3 智能接口
154 var voice = {
155 localId: '',
156 serverId: ''
157 };
158 // 3.1 识别音频并返回识别结果
159 document.querySelector('#translateVoice').onclick = function () {
160 if (voice.localId == '') {
161 alert('请先使用 startRecord 接口录制一段声音');
162 return;
163 }
164 wx.translateVoice({
165 localId: voice.localId,
166 complete: function (res) {
167 if (res.hasOwnProperty('translateResult')) {
168 alert('识别结果:' + res.translateResult);
169 } else {
170 alert('无法识别');
171 }
172 }
173 });
174 };
175
176 // 4 音频接口
177 // 4.2 开始录音
178 document.querySelector('#startRecord').onclick = function () {
179 wx.startRecord({
180 cancel: function () {
181 alert('用户拒绝授权录音');
182 }
183 });
184 };
185
186 // 4.3 停止录音
187 document.querySelector('#stopRecord').onclick = function () {
188 wx.stopRecord({
189 success: function (res) {
190 voice.localId = res.localId;
191 },
192 fail: function (res) {
193 alert(JSON.stringify(res));
194 }
195 });
196 };
197
198 // 4.4 监听录音自动停止
199 wx.onVoiceRecordEnd({
200 complete: function (res) {
201 voice.localId = res.localId;
202 alert('录音时间已超过一分钟');
203 }
204 });
205
206 // 4.5 播放音频
207 document.querySelector('#playVoice').onclick = function () {
208 if (voice.localId == '') {
209 alert('请先使用 startRecord 接口录制一段声音');
210 return;
211 }
212 wx.playVoice({
213 localId: voice.localId
214 });
215 };
216
217 // 4.6 暂停播放音频
218 document.querySelector('#pauseVoice').onclick = function () {
219 wx.pauseVoice({
220 localId: voice.localId
221 });
222 };
223
224 // 4.7 停止播放音频
225 document.querySelector('#stopVoice').onclick = function () {
226 wx.stopVoice({
227 localId: voice.localId
228 });
229 };
230
231 // 4.8 监听录音播放停止
232 wx.onVoicePlayEnd({
233 complete: function (res) {
234 alert('录音(' + res.localId + ')播放结束');
235 }
236 });
237
238 // 4.8 上传语音
239 document.querySelector('#uploadVoice').onclick = function () {
240 if (voice.localId == '') {
241 alert('请先使用 startRecord 接口录制一段声音');
242 return;
243 }
244 wx.uploadVoice({
245 localId: voice.localId,
246 success: function (res) {
247 alert('上传语音成功,serverId 为' + res.serverId);
248 voice.serverId = res.serverId;
249 }
250 });
251 };
252
253 // 4.9 下载语音
254 document.querySelector('#downloadVoice').onclick = function () {
255 if (voice.serverId == '') {
256 alert('请先使用 uploadVoice 上传声音');
257 return;
258 }
259 wx.downloadVoice({
260 serverId: voice.serverId,
261 success: function (res) {
262 alert('下载语音成功,localId 为' + res.localId);
263 voice.localId = res.localId;
264 }
265 });
266 };
267
268 // 5 图片接口
269 // 5.1 拍照、本地选图
270 var images = {
271 localId: [],
272 serverId: []
273 };
274 document.querySelector('#chooseImage').onclick = function () {
275 wx.chooseImage({
276 success: function (res) {
277 images.localId = res.localIds;
278 alert('已选择 ' + res.localIds.length + ' 张图片');
279 }
280 });
281 };
282
283 // 5.2 图片预览
284 document.querySelector('#previewImage').onclick = function () {
285 wx.previewImage({
286 current: 'http://img5.douban.com/view/photo/photo/public/p1353993776.jpg',
287 urls: [
288 'http://img3.douban.com/view/photo/photo/public/p2152117150.jpg',
289 'http://img5.douban.com/view/photo/photo/public/p1353993776.jpg',
290 'http://img3.douban.com/view/photo/photo/public/p2152134700.jpg'
291 ]
292 });
293 };
294
295 // 5.3 上传图片
296 document.querySelector('#uploadImage').onclick = function () {
297 if (images.localId.length == 0) {
298 alert('请先使用 chooseImage 接口选择图片');
299 return;
300 }
301 var i = 0, length = images.localId.length;
302 images.serverId = [];
303 function upload() {
304 wx.uploadImage({
305 localId: images.localId[i],
306 success: function (res) {
307 i++;
308 //alert('已上传:' + i + '/' + length);
309 images.serverId.push(res.serverId);
310 if (i < length) {
311 upload();
312 }
313 },
314 fail: function (res) {
315 alert(JSON.stringify(res));
316 }
317 });
318 }
319 upload();
320 };
321
322 // 5.4 下载图片
323 document.querySelector('#downloadImage').onclick = function () {
324 if (images.serverId.length === 0) {
325 alert('请先使用 uploadImage 上传图片');
326 return;
327 }
328 var i = 0, length = images.serverId.length;
329 images.localId = [];
330 function download() {
331 wx.downloadImage({
332 serverId: images.serverId[i],
333 success: function (res) {
334 i++;
335 alert('已下载:' + i + '/' + length);
336 images.localId.push(res.localId);
337 if (i < length) {
338 download();
339 }
340 }
341 });
342 }
343 download();
344 };
345
346 // 6 设备信息接口
347 // 6.1 获取当前网络状态
348 document.querySelector('#getNetworkType').onclick = function () {
349 wx.getNetworkType({
350 success: function (res) {
351 alert(res.networkType);
352 },
353 fail: function (res) {
354 alert(JSON.stringify(res));
355 }
356 });
357 };
358
359 // 7 地理位置接口
360 // 7.1 查看地理位置
361 document.querySelector('#openLocation').onclick = function () {
362 wx.openLocation({
363 latitude: 23.099994,
364 longitude: 113.324520,
365 name: 'TIT 创意园',
366 address: '广州市海珠区新港中路 397 号',
367 scale: 14,
368 infoUrl: 'http://weixin.qq.com'
369 });
370 };
371
372 // 7.2 获取当前地理位置
373 document.querySelector('#getLocation').onclick = function () {
374 wx.getLocation({
375 success: function (res) {
376 alert(JSON.stringify(res));
377 },
378 cancel: function (res) {
379 alert('用户拒绝授权获取地理位置');
380 }
381 });
382 };
383
384 // 8 界面操作接口
385 // 8.1 隐藏右上角菜单
386 document.querySelector('#hideOptionMenu').onclick = function () {
387 wx.hideOptionMenu();
388 };
389
390 // 8.2 显示右上角菜单
391 document.querySelector('#showOptionMenu').onclick = function () {
392 wx.showOptionMenu();
393 };
394
395 // 8.3 批量隐藏菜单项
396 document.querySelector('#hideMenuItems').onclick = function () {
397 wx.hideMenuItems({
398 menuList: [
399 'menuItem:readMode', // 阅读模式
400 'menuItem:share:timeline', // 分享到朋友圈
401 'menuItem:copyUrl' // 复制链接
402 ],
403 success: function (res) {
404 alert('已隐藏“阅读模式”,“分享到朋友圈”,“复制链接”等按钮');
405 },
406 fail: function (res) {
407 alert(JSON.stringify(res));
408 }
409 });
410 };
411
412 // 8.4 批量显示菜单项
413 document.querySelector('#showMenuItems').onclick = function () {
414 wx.showMenuItems({
415 menuList: [
416 'menuItem:readMode', // 阅读模式
417 'menuItem:share:timeline', // 分享到朋友圈
418 'menuItem:copyUrl' // 复制链接
419 ],
420 success: function (res) {
421 alert('已显示“阅读模式”,“分享到朋友圈”,“复制链接”等按钮');
422 },
423 fail: function (res) {
424 alert(JSON.stringify(res));
425 }
426 });
427 };
428
429 // 8.5 隐藏所有非基本菜单项
430 document.querySelector('#hideAllNonBaseMenuItem').onclick = function () {
431 wx.hideAllNonBaseMenuItem({
432 success: function () {
433 alert('已隐藏所有非基本菜单项');
434 }
435 });
436 };
437
438 // 8.6 显示所有被隐藏的非基本菜单项
439 document.querySelector('#showAllNonBaseMenuItem').onclick = function () {
440 wx.showAllNonBaseMenuItem({
441 success: function () {
442 alert('已显示所有非基本菜单项');
443 }
444 });
445 };
446
447 // 8.7 关闭当前窗口
448 document.querySelector('#closeWindow').onclick = function () {
449 wx.closeWindow();
450 };
451
452 // 9 微信原生接口
453 // 9.1.1 扫描二维码并返回结果
454 document.querySelector('#scanQRCode0').onclick = function () {
455 wx.scanQRCode();
456 };
457 // 9.1.2 扫描二维码并返回结果
458 document.querySelector('#scanQRCode1').onclick = function () {
459 wx.scanQRCode({
460 needResult: 1,
461 desc: 'scanQRCode desc',
462 success: function (res) {
463 alert(JSON.stringify(res));
464 }
465 });
466 };
467
468 // 10 微信支付接口
469 // 10.1 发起一个支付请求
470 document.querySelector('#chooseWXPay').onclick = function () {
471 // 注意:此 Demo 使用 2.7 版本支付接口实现,建议使用此接口时参考微信支付相关最新文档。
472 wx.chooseWXPay({
473 timestamp: 1414723227,
474 nonceStr: 'noncestr',
475 package: 'addition=action_id%3dgaby1234%26limit_pay%3d&bank_type=WX&body=innertest&fee_type=1&input_charset=GBK¬ify_url=http%3A%2F%2F120.204.206.246%2Fcgi-bin%2Fmmsupport-bin%2Fnotifypay&out_trade_no=1414723227818375338&partner=1900000109&spbill_create_ip=127.0.0.1&total_fee=1&sign=432B647FE95C7BF73BCD177CEECBEF8D',
476 signType: 'SHA1', // 注意:新版支付接口使用 MD5 加密
477 paySign: 'bd5b1933cda6e9548862944836a9b52e8c9a2b69'
478 });
479 };
480
481 // 11.3 跳转微信商品页
482 document.querySelector('#openProductSpecificView').onclick = function () {
483 wx.openProductSpecificView({
484 productId: 'pDF3iY_m2M7EQ5EKKKWd95kAxfNw',
485 extInfo: '123'
486 });
487 };
488
489 // 12 微信卡券接口
490 // 12.1 添加卡券
491 document.querySelector('#addCard').onclick = function () {
492 wx.addCard({
493 cardList: [
494 {
495 cardId: 'pDF3iY9tv9zCGCj4jTXFOo1DxHdo',
496 cardExt: '{"code": "", "openid": "", "timestamp": "1418301401", "signature":"f54dae85e7807cc9525ccc127b4796e021f05b33"}'
497 },
498 {
499 cardId: 'pDF3iY9tv9zCGCj4jTXFOo1DxHdo',
500 cardExt: '{"code": "", "openid": "", "timestamp": "1418301401", "signature":"f54dae85e7807cc9525ccc127b4796e021f05b33"}'
501 }
502 ],
503 success: function (res) {
504 alert('已添加卡券:' + JSON.stringify(res.cardList));
505 }
506 });
507 };
508
509 var codes = [];
510 // 12.2 选择卡券
511 document.querySelector('#chooseCard').onclick = function () {
512 wx.chooseCard({
513 cardSign: '8ef8aa071f1d2186cb1355ec132fed04ebba1c3f',
514 timestamp: 1437997723,
515 nonceStr: 'k0hGdSXKZEj3Min5',
516 success: function (res) {
517 res.cardList = JSON.parse(res.cardList);
518 encrypt_code = res.cardList[0]['encrypt_code'];
519 alert('已选择卡券:' + JSON.stringify(res.cardList));
520 decryptCode(encrypt_code, function (code) {
521 codes.push(code);
522 });
523 }
524 });
525 };
526
527 // 12.3 查看卡券
528 document.querySelector('#openCard').onclick = function () {
529 if (codes.length < 1) {
530 alert('请先使用 chooseCard 接口选择卡券。');
531 return false;
532 }
533 var cardList = [];
534 for (var i = 0; i < codes.length; i++) {
535 cardList.push({
536 cardId: 'pDF3iY9tv9zCGCj4jTXFOo1DxHdo',
537 code: codes[i]
538 });
539 }
540 wx.openCard({
541 cardList: cardList
542 });
543 };
544
545 var shareData = {
546 title: '微信JS-SDK Demo',
547 desc: '微信JS-SDK,帮助第三方为用户提供更优质的移动web服务',
548 link: 'http://demo.open.weixin.qq.com/jssdk/',
549 imgUrl: 'http://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRt8Qia4lv7k3M9J1SKqKCImxJCt7j9rHYicKDI45jRPBxdzdyREWnk0ia0N5TMnMfth7SdxtzMvVgXg/0'
550 };
551 wx.onMenuShareAppMessage(shareData);
552 wx.onMenuShareTimeline(shareData);
553
554 function decryptCode(code, callback) {
555 $.getJSON('/jssdk/decrypt_code.php?code=' + encodeURI(code), function (res) {
556 if (res.errcode == 0) {
557 codes.push(res.code);
558 }
559 });
560 }
561 });
562
563 wx.error(function (res) {
564 alert(res.errMsg);
565 });
3、后台部分
1 <?php
2 class JSSDK {
3 private $appId;
4 private $appSecret;
5
6 public function __construct($appId, $appSecret) {
7 $this->appId = $appId;
8 $this->appSecret = $appSecret;
9 }
10
11 public function getSignPackage() {
12 $jsapiTicket = $this->getJsApiTicket();
13
14 // 注意 URL 一定要动态获取,不能 hardcode.
15 $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
16 $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
17
18 $timestamp = time();
19 $nonceStr = $this->createNonceStr();
20
21 // 这里参数的顺序要按照 key 值 ASCII 码升序排序
22 $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
23
24 $signature = sha1($string);
25
26 $signPackage = array(
27 "appId" => $this->appId,
28 "nonceStr" => $nonceStr,
29 "timestamp" => $timestamp,
30 "url" => $url,
31 "signature" => $signature,
32 "rawString" => $string
33 );
34 return $signPackage;
35 }
36
37 private function createNonceStr($length = 16) {
38 $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
39 $str = "";
40 for ($i = 0; $i < $length; $i++) {
41 $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
42 }
43 return $str;
44 }
45
46 private function getJsApiTicket() {
47 // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
48 $data = json_decode(file_get_contents("jsapi_ticket.json"));
49 if ($data->expire_time < time()) {
50 $accessToken = $this->getAccessToken();
51 // 如果是企业号用以下 URL 获取 ticket
52 // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
53 $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
54 $res = json_decode($this->httpGet($url));
55 $ticket = $res->ticket;
56 if ($ticket) {
57 $data->expire_time = time() + 7000;
58 $data->jsapi_ticket = $ticket;
59 $fp = fopen("jsapi_ticket.json", "w");
60 fwrite($fp, json_encode($data));
61 fclose($fp);
62 }
63 } else {
64 $ticket = $data->jsapi_ticket;
65 }
66
67 return $ticket;
68 }
69
70 private function getAccessToken() {
71 // access_token 应该全局存储与更新,以下代码以写入到文件中做示例
72 $data = json_decode(file_get_contents("access_token.json"));
73 if ($data->expire_time < time()) {
74 // 如果是企业号用以下URL获取access_token
75 // $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
76 $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
77 $res = json_decode($this->httpGet($url));
78 $access_token = $res->access_token;
79 if ($access_token) {
80 $data->expire_time = time() + 7000;
81 $data->access_token = $access_token;
82 $fp = fopen("access_token.json", "w");
83 fwrite($fp, json_encode($data));
84 fclose($fp);
85 }
86 } else {
87 $access_token = $data->access_token;
88 }
89 return $access_token;
90 }
91
92 private function httpGet($url) {
93 $curl = curl_init();
94 curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
95 curl_setopt($curl, CURLOPT_TIMEOUT, 500);
96 // 为保证第三方服务器与微信服务器之间数据传输的安全性,所有微信接口采用https方式调用,必须使用下面2行代码打开ssl安全校验。
97 // 如果在部署过程中代码在此处验证失败,请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
98 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
99 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
100 curl_setopt($curl, CURLOPT_URL, $url);
101
102 $res = curl_exec($curl);
103 curl_close($curl);
104
105 return $res;
106 }
107 }
注意:
1、示例代码只是讲解整体流程,关于路径部分可自行调整
2、由于app_secret比较保密,建议保存在服务端,由后台发起