微信公众号带参二维码的生成与解析(java)
2017-10-02 00:00:00

这些日子一直在做微信公众号的开发,从头开始学,觉得特别复杂,接口一堆,开发文档看不懂,各种bug,由于现在二维码的广泛流传,接触了带参二维码,写一下生成与解析

带参二维码介绍

为了满足我们这些用户的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。说白了就是可以生成带参数的二维码,后台可以根据参数做出不同的反应,然后推送信息给用户,使一些操作简单化。

目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1–100000),而且参数只能是整数。

用户扫描带场景值二维码时,可能推送以下两种事件:
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

带参二维码的生成

1.首先创建二维码ticket,然后凭借ticket到指定URL换取二维码
2.然后会返回一个链接,打开就是一个二维码

当然这些前提就是有公众号并且前期的开发配置已完成,服务器域名什么的都配好了,也认证了,或者用的测试号都可以

创建二维码ticket需要提供一个开发者自行设定的参数(scene_id),这个就是所谓的参数(整数)

http请求URL
https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN

POST数据格式(临时二维码)

{ “expire_seconds”: 1800,”action_name”: “QR_SCENE”,”action_info”: {“scene”: {“scene_id”: 100000}}}

其中expire_seconds就是存在的时间,action_name确定二维码是永久的还是临时的,详细参数的可以看微信开发文档。

返回格式:(临时二维码)

{“ticket”:”gQFK8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL3kweXE0T3JscWY3UTltc3ZPMklvAAIEG9jUUgMECAcAAA==”,”expire_seconds”: 1800}

代码:

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
JSONObject tjsonObj = getTicketJsonObj(6,604800);
String ticketString = tjsonObj.getString("ticket");
int expire_seconds = tjsonObj.getInt("expire_seconds");
String url = tjsonObj.getString("url");
System.out.println("ticketString:"+ticketString);
System.out.println("expire_seconds:"+expire_seconds);
System.out.println("url:"+url);
String qrcodeUrl = getQrcodeUrl(tjsonObj);
System.out.println("qrcodeUrl:"+qrcodeUrl);

public static JSONObject getTicketJsonObj(int scene_id,int expire_seconds){
StringBuffer ticket = new StringBuffer();
ticket.append("{\"expire_seconds\":");
ticket.append(Integer.toString(expire_seconds));
ticket.append(",\"action_name\":\"QR_SCENE\",");
ticket.append("\"action_info\":{\"scene\":{\"scene_id\":");
ticket.append(Integer.toString(scene_id));
ticket.append("}}}");
AccessTokenDao atDao = new AccessTokenDao();
atDao.checkToken();
String token = atDao.getAccessTokenBySQL().getToken();
String url = TICKET_URL.replace("TOKEN", token);
String ticket1 = new String(ticket);
return doPostStr(url, ticket1);
}
public static JSONObject doPostStr(String url,String outStr){
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
JSONObject jsonObject =null;
try {
httpPost.setEntity(new StringEntity(outStr, "utf-8"));
HttpResponse response = httpClient.execute(httpPost);
String result = EntityUtils.toString(response.getEntity(),"utf-8");
jsonObject = JSONObject.fromObject(result);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonObject;
}
public static String getQrcodeUrl(JSONObject ticketObj){
String ticketString = ticketObj.getString("ticket");
String url =null;
try {
url = QRCODE_URL.replace("TICKET", URLEncoder.encode(ticketString,"utf-8"));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return url;
}

现在就得到了url,打开就是二维码的图片

带参二维码的解析

微信公众平台推送的消息一般是xml来做的。
用户扫描带场景值二维码时,可能推送以下两种事件:
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。

  1. 用户未关注时,进行关注后的事件推送
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <xml>
    <ToUserName><![CDATA[gh_45072270791c]]></ToUserName>
    <FromUserName><![CDATA[o7Lp5t6n59DeX3U0C7Kric9qEx-Q]]></FromUserName>
    <CreateTime>1389684286</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[subscribe]]></Event>
    <EventKey><![CDATA[qrscene_1000]]></EventKey>
    <Ticket><![CDATA[gQHi8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0UweTNxNi1sdlA3RklyRnNKbUFvAAIELdnUUgMEAAAAAA==]]></Ticket>
    </xml>
    其中EventKey包括参数。
  2. 用户已关注时的事件推送
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <xml>
    <ToUserName><![CDATA[gh_45072270791c]]></ToUserName>
    <FromUserName><![CDATA[o7Lp5t6n59DeX3U0C7Kric9qEx-Q]]></FromUserName>
    <CreateTime>1389684184</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[SCAN]]></Event>
    <EventKey><![CDATA[1000]]></EventKey>
    <Ticket><![CDATA[gQHi8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL0UweTNxNi1sdlA3RklyRnNKbUFvAAIELdnUUgMEAAAAAA==]]></Ticket>
    </xml>
    然后就可以解析这些事件,来做出响应。
    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
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

    request.setCharacterEncoding("utf-8");
    response.setCharacterEncoding("utf-8");

    PrintWriter out = response.getWriter();
    try {
    Map<String, String> map = MessageUtil.xmlToMap(request);
    String toUserName = map.get("ToUserName");
    String fromUserName = map.get("FromUserName");// openid
    String msgType = map.get("MsgType");
    String content = map.get("Content");
    String message = null;
    if (MessageUtil.MESSAGE_TEXT.equals(msgType)) {

    }
    } else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) {

    }
    } catch (DocumentException e) {
    e.printStackTrace();
    } finally {
    out.close();
    }

    }
    自己可以做一些相关的功能实现或者返回消息给用户

代码部分是网上的,部分是自己的,写的不好,只是一个大概的方法步骤。
如有错误,希望指出