微信公众号-网页开发 开发入门

Tips:
本文章主要基于微信JS-SDK和jQuery WeUI 进行的微信公众号网页开发。前提需要
1.微信公众号已经完成开发者认证。
2.在“基本配置”中设置IP白名单。
3.提供一个能支持80或者443的服务。

微信官方文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

绑定域名

先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。

引入JS文件

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js

获取access_token

access_token 用户获取jsapi_ticket,有效期7200秒,开发者必须在自己的服务全局缓存access_token。
建议开发者建立自己的access_token中控服务器统一获取和刷新,其他业务逻辑服务器所使用的access_token均来自于该中控服务器。 微信获取access_token接口文档

接口调用说明
前提调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。
1
2
https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

我这里使用了shell脚本获取access_token。

1
2
3
a_url=`curl https://api.weixin.qq.com/cgi-bin/token\?grant_type\=client_credential\&appid\=xxx\&secret\=xxxx`
access_token=`echo $a_url|jq -r '.access_token'`
echo $access_token

tips: jq 是linux下shell进行json处理的工具,很强大。

可以使用这个地址测试该接口 使用网页调试工具调试该接口

获取jsapi_ticket

获取jsapi_ticket需要用到上一步的access_token,轻重jsapi_ticket有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket。

1
2
3
4
5
6
7
8
9
https请求方式: GET
# https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}

我这里使用了shell脚本来获取,并且保存到文件。

1
2
3
t_url=`curl https://api.weixin.qq.com/cgi-bin/ticket/getticket\?access_token\=$access_token\&type\=jsapi`
ticket=`echo $t_url | jq -r '.ticket'`
echo $ticket > /opt/tomcat/darenweb_8087/webapps/wx/ticket.txt

我这里为了方便使用了crontab定时器每两个小时同步一次access_token和ticket,在生产环境中最好根据expires_in过期时间进行同步。
定时脚本如下:

1
00 */2 * * * /bin/bash /server/scripts/get_wx_ticket.sh

至此完成了access_token和ticket的获取。

网页开发 通过js config接口注入权限验证配置

1
2
3
4
5
6
7
8
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。
在config之前需要对config所需参数进行签名,获取config方法网页端如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
function getWxTicket(){
$.ajax({
// url: "http://localhost:8080/aa/sign?originUrl=http://localhost:8080/login.html",
url: "http://xxxx/sign?originUrl="+window.location.href,
type: "GET",
dataType: 'json',
// crossDomain: true,
// jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
// jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function (response) {
// alert("11111111");
wxConfig = response;

if (isDebug){
// window.access_token = response.access_token;
alert(wxConfig.timestamp);
alert(wxConfig.nonce);
alert(wxConfig.jsapi_ticket);
}
Wx_config();
}
});
}


function Wx_config() {

wx.ready(function () {
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
if (isDebug) {
alert("ready");
}

//在微信网页端 隐藏不需要的功能按钮
wx.hideMenuItems({
menuList: ['menuItem:share:appMessage',
'menuItem:share:timeline',
'menuItem:share:qq',
'menuItem:share:weiboApp',
'menuItem:share:facebook',
'menuItem:share:QZone',
'menuItem:editTag',
'menuItem:delete',
'menuItem:copyUrl',
'menuItem:originPage',
'menuItem:openWithQQBrowser',
'menuItem:openWithSafari',
'menuItem:share:email',
'menuItem:favorite'], // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
success: function (res) {
}
});
});
/*
* 注意:
* 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
* 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。
* 3. 完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
*/
wx.error(function (res) {
if (isDebug) {

alert("error");
alert(res);
}
});
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: 'wx040138c462be4cb0', // 必填,公众号的唯一标识
timestamp: wxConfig.timestamp, // 必填,生成签名的时间戳
nonceStr: wxConfig.nonce, // 必填,生成签名的随机串
signature: wxConfig.signature,// 必填,签名
jsApiList: [
'hideMenuItems',
'showMenuItems',
'hideAllNonBaseMenuItem',
'showAllNonBaseMenuItem',
'chooseImage',
'previewImage',
'uploadImage',
'downloadImage',
'getNetworkType',
'openLocation',
'getLocation',
'hideOptionMenu',
'showOptionMenu',
'closeWindow',
'scanQRCode',
'chooseWXPay',
'openProductSpecificView',
'addCard',
'chooseCard',
'openCard'] // 必填,需要使用的JS接口列表
});
}

后台进行签名,签名算法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
*
* @param originUrl 需要加密的URL
* @param request
* @param response
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes", "null" })
@RequestMapping(value = "/sign", method = RequestMethod.GET)
@ResponseBody
public HashMap getSignature(String originUrl , HttpServletRequest request, HttpServletResponse response) {

File file = new File("/opt/tomcat/darenweb_8087/webapps/wx/ticket.txt");
StringBuilder ticket = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String tempString = null;
int line = 1;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null) {
// 显示行号
ticket.append(tempString);
}
reader.close();

} catch (Exception e) {
e.printStackTrace();
}
//2、获取Ticket
String jsapi_ticket = ticket.toString();
//3、时间戳和随机字符串
String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳

//4、获取url
String url= originUrl;


String string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + noncestr
+ "&timestamp=" + timestamp + "&url=" + url;
MessageDigest crypt = null;
try {
crypt = MessageDigest.getInstance("SHA-1");

crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
String signature = byteToHex(crypt.digest());

HashMap<String,String> map = new HashMap<>();
map.put("signature",signature);
map.put("timestamp",timestamp);
map.put("jsapi_ticket",jsapi_ticket);
map.put("nonce",noncestr);
return map;
}

至此完成了微信号网页开发的配置和授权。

参考资料

分享到