针对不同的推广场景,生成特定的公众号二维码,以便系统统计用户来源,提供个性化服务;
通过微信公众号提供的生成带参数的二维码来实现用户来源的识别。
目前有两类带参数的二维码:
当用户扫描带场景的二维码时,微信系统将向响应系统(什么是微信系统和响应系统?点击传送门)推送以下两种事件:
获取二维码一共分两步:
因为有两种二维码,所以也有两种ticket
获取临时二维码ticket:
请求方式: POST
地址: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
数据格式:json
数据示例:
场景值为整型数字:
{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}
场景值为字符串:
{"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}
获取永久二维码ticket:
请求方式: POST
地址: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
数据格式:json
数据示例:
场景值为整型数字:
{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": 123}}}
场景值为字符串:
{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}
返回结果说明:
{"ticket":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm
3sUw==","expire_seconds":60,"url":"http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI"}
首先贴上官方对参数的说明:
参数 | 说明 |
---|---|
expire_seconds | 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。 |
action_name | 二维码类型,QR_SCENE为临时的整型参数值,QR_STR_SCENE为临时的字符串参数值,QR_LIMIT_SCENE为永久的整型参数值,QR_LIMIT_STR_SCENE为永久的字符串参数值 |
action_info | 二维码详细信息 |
scene_id | 场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1–100000) |
scene_str | 场景值ID(字符串形式的ID),字符串类型,长度限制为1到64 |
个人觉得不好理解的是action_name。
首先我们可以发现获取临时和永久ticket的地址是一样的!这说明我们需要传递一些信息告诉微信系统我们需要的是什么;然后我们可以发现的就是json的属性不一样,于是就产生了这样的疑问:是不是通过expire_seconds这个字段判断的呢?
接下里看参数说明,action_name的介绍为:“QR_SCENE为临时的整型参数值”。我没明白的是QR_SCENE到底是一个整型参数值,还是一个标记值。因为看到了参数值,所以就理解为“可变”的了,加上我们也的确有判断是否是永久的方法(expire_seconds存在与否),于是似乎理所当然。。。就出错了。
事实上,它是一个标记值,也就是微信系统应该是通过action_name来判断我们的目的是什么。不过问题也不大,程序跑起来就能明白这个问题到底是什么了,因为随意指定该属性的值会抛错:“invalid action name”;
获得ticket的同时,我们也获得了一个URL,这个URL即为二维码解析后的地址,此时我们就可以自己为该地址生成二维码图片了,比如美化一下什么的。不过我们也可以从微信系统那里获取下载地址。
GET请求(请使用https协议)https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
提醒:TICKET记得进行UrlEncode
访问该地址即可获得对应场景、对应生命周期的二维码图片下载地址;
public class Main {
public static void main(String[] args){
//获取临时推广、场景值为字符串的二维码
String temporaryQRCodeUrl= WeChatQRCodeManager.getTemporaryStrQRCodeDownloadUrl("teacher_wang");
System.out.println(temporaryQRCodeUrl);
//获取永久推广、场景值为字符串的二维码
String permanentQRCodeUrl= WeChatQRCodeManager.getPermanentStrQRCodeDownloadUrl("teacher_liu");
System.out.println(permanentQRCodeUrl);
//获取临时推广、场景值为整型的二维码
temporaryQRCodeUrl= WeChatQRCodeManager.getTemporaryIntQRCodeDownloadUrl(120);
System.out.println(temporaryQRCodeUrl);
//获取永久推广、场景值为整型的二维码
permanentQRCodeUrl= WeChatQRCodeManager.getPermanentIntQRCodeDownloadUrl(119);
System.out.println(permanentQRCodeUrl);
}
}
public class WeChatQRCodeManager {
/**
* 获取临时特定场景推广二维码下载地址
* @param sceneStr 临时特定场景的字符串标记
* @return 二维码的下载地址
* @see QRCodeInfo
*/
public static String getTemporaryStrQRCodeDownloadUrl(String sceneStr){
QRCodeInfo info=new QRCodeInfo(false);
info.setSceneStrId(sceneStr);
return getQRCodeDownloadUrl(info);
}
/**
* 获取永久特定场景推广二维码下载地址
* @param sceneStr 永久特定场景的字符串标记
* @return 二维码的下载地址
* @see QRCodeInfo
*/
public static String getPermanentStrQRCodeDownloadUrl(String sceneStr){
QRCodeInfo info=new QRCodeInfo(true);
info.setSceneStrId(sceneStr);
return getQRCodeDownloadUrl(info);
}
/**
* 获取临时特定场景推广二维码下载地址
* @param sceneInt 临时特定场景的整型标记
* @return 二维码的下载地址
* @see QRCodeInfo
*/
public static String getTemporaryIntQRCodeDownloadUrl(int sceneInt){
QRCodeInfo info=new QRCodeInfo(false);
info.setSceneIntId(sceneInt);
return getQRCodeDownloadUrl(info);
}
/**
* 获取永久特定场景推广二维码下载地址
* @param sceneInt 永久特定场景的整型标记
* @return 二维码的下载地址
* @see QRCodeInfo
*/
public static String getPermanentIntQRCodeDownloadUrl(int sceneInt){
QRCodeInfo info=new QRCodeInfo(true);
info.setSceneIntId(sceneInt);
return getQRCodeDownloadUrl(info);
}
/**
* 获取二维码下载地址
* @param info 二维码信息载体
* @return 二维码下载地址
* @see QRCodeInfo
*/
private static String getQRCodeDownloadUrl(QRCodeInfo info) {
String responseString= HttpUtils.doPostJson(WeChatUrlManager.getQrCodeTicketUrl(),info.toJsonString());
String ticket= JsonUtils.getTargetStringInfo("ticket",responseString);
return WeChatUrlManager.getQrCodeUrl(ticket);
}
}
/**
* @author Shao Lixuan 2019/3/7 16:43
*/
public class QRCodeInfo {
private int expireSeconds;
private String sceneStrId;
private boolean isTemporary;
private int sceneIntId;
private boolean sceneIsStr;
public QRCodeInfo(boolean temporary){
isTemporary=temporary;
sceneIsStr=true;
}
public boolean isTemporary() {
return isTemporary;
}
public void setTemporary(boolean temporary) {
isTemporary = temporary;
}
public int getExpireSeconds() {
return expireSeconds;
}
public void setExpireSeconds(int expireSeconds) {
this.expireSeconds = expireSeconds;
}
public String getSceneStrId() {
return sceneStrId;
}
public void setSceneStrId(String sceneStrId) {
this.sceneStrId = sceneStrId;
sceneIsStr=true;
}
public int getSceneIntId() {
return sceneIntId;
}
public void setSceneIntId(int sceneIntId) {
this.sceneIntId = sceneIntId;
sceneIsStr=false;
}
public String toJsonString(){
String template;
if(isTemporary){
if(sceneIsStr) {
template = "{\"expire_seconds\": %d, \"action_name\":\"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"%s\"}}}";
return String.format(template, expireSeconds, sceneStrId);
}else{
template = "{\"expire_seconds\": %d, \"action_name\":\"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": %d}}}";
return String.format(template, expireSeconds, sceneIntId);
}
}else {
if(sceneIsStr) {
template = "{\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"%s\"}}}";
return String.format(template, sceneStrId);
}else{
template = "{\"action_name\": \"QR_LIMIT_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": %d}}}";
return String.format(template, sceneStrId);
}
}
}
}
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGh8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyQllPSkFXRnVmRUMxMDAwMHcwN0QAAgRA5IBcAwQAAAAA
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGG8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyMEtZaEJYRnVmRUMxS3NBMTFzY18AAgRg5IFcAwQ8AAAA
https://mp.weixin.qq.com/cgi-bin/sho wqrcode?ticket=gQHH8TwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyaGFiTEFiRnVmRUMxMDAwMGcwM1EAAgTj04FcAwQAAAAA
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGK8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyRVZNMUJTRnVmRUMxS3NBMXhzMW4AAgRg5IFcAwQ8AAAA
项目源码CSDN下载