微信JSSDK开发JAVA版实现

来源:互联网 发布:php pack函数 编辑:程序博客网 时间:2024/05/21 11:05

JSSDK JAVA开发第一步:绑定域名

先登录微信公众平台进入“公众号设置”(作者:在页面左下角,认证订阅号,认证服务号皆可配置)

(备注:登录后可在“开发者中心”可查看对应的接口权限。)

set.jpg

再选择页面上方“功能设置”

1.jpg

这时可以看到“JS接口安全域名”。点击设置弹出以下输入框,按照要求填写域名(注意:IP不可用)

如:www.ipastimes.com, ipastimes.com,  examples.ipastimes.com 可用

2.jpg

JSSDK JAVA开发第二步:引入微信JS

    在需要引用微信JS接口的页面引入微信js文件(微信在其浏览器内置wx对象)http://res.wx.qq.com/open/js/jweixin-1.0.0.js

JSSDK JAVA开发第三步:后台实现签名逻辑

    1.获取access_token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    /**
     * 获取接口访问凭证
     
     * @param appid 凭证
     * @param appsecret 密钥
     * @return
     */
    public static String getAccess_token(String appid, String appsecret) {
            //凭证获取(GET)
            String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
        // 发起GET请求获取凭证
        JSONObject jsonObject = httpsRequest(requestUrl, "GET"null);
                String access_token = null;
        if (null != jsonObject) {
            try {
                access_token = jsonObject.getString("access_token");
            catch (JSONException e) {
                // 获取token失败
                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return access_token;
    }

    2.获取jsapi_ticket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
     * 调用微信JS接口的临时票据
     
     * @param access_token 接口访问凭证
     * @return
     */
    public static String getJsApiTicket(String access_token) {
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
        String requestUrl = url.replace("ACCESS_TOKEN", access_token);
        // 发起GET请求获取凭证
        JSONObject jsonObject = httpsRequest(requestUrl, "GET"null);
        String ticket = null;
        if (null != jsonObject) {
            try {
                ticket = jsonObject.getString("ticket");
            catch (JSONException e) {
                // 获取token失败
                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return ticket;
    }

3.实现签名逻辑(根据官方sample改)

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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
 
import javax.servlet.http.HttpServletRequest;
 
import net.sf.json.JSONObject;
 
import org.apache.struts2.ServletActionContext;
 
public class PastUtil {
    public static Token token = null;
    public static String time = null;
    public static String jsapi_ticket = null;
    /**
     
     * @param appId   公账号appId
     * @param appSecret
     * @param url    当前网页的URL,不包含#及其后面部分
     * @return
     */
    public static String getParam(String appId,String appSecret){
        if(token == null){
            token = CommonUtil.getToken(appId, appSecret);
            jsapi_ticket = CommonUtil.getJsApiTicket(token.getAccessToken());
            time = getTime();
        }else{
            if(!time.substring(013).equals(getTime().substring(013))){ //每小时刷新一次
                token = null;
                token = CommonUtil.getToken(appId, appSecret);
                jsapi_ticket = CommonUtil.getJsApiTicket(token.getAccessToken());
                time = getTime();
            }
        }
         
        String url = getUrl();
         
        Map<String, String> params = sign(jsapi_ticket, url);
        params.put("appid", appId);
         
        JSONObject jsonObject = JSONObject.fromObject(params);  
        String jsonStr = jsonObject.toString();
        System.out.println(jsonStr);
        return jsonStr;
    }
     
    private static String getUrl(){
        HttpServletRequest request = ServletActionContext.getRequest();
         
        StringBuffer requestUrl = request.getRequestURL();
         
        String queryString = request.getQueryString();
        String url = requestUrl +"?"+queryString;
        return url;
    }
     
    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String str;
        String signature = "";
 
        //注意这里参数名必须全部小写,且必须有序
        str = "jsapi_ticket=" + jsapi_ticket +
                  "&noncestr=" + nonce_str +
                  "&timestamp=" + timestamp +
                  "&url=" + url;
 
        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
 
        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
 
        return ret;
    }
 
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
 
    private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }
 
    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
     
    //获取当前系统时间 用来判断access_token是否过期
    public static String getTime(){
        Date dt=new Date();
        SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(dt);
    }
}

大部分开发者在签名认证处出错,开启debug模式,当进入页面时会alert出如下信息:

1.jpg

按照如下步骤排错:

1.确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。

2.确认config中noncestr, timestamp与用以签名中的对应noncestr, timestamp一致。

3.确认url是页面完整的url,包括GET参数部分。

4.确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。

5.确保一定缓存access_token和jsapi_ticket,可以减少两次服务器请求加速体验外,还避免了触发频率限制,提高服务稳定性。

附JS SDK权限表

JSSDK 权限.jpg

更多信息请参考:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

0 2