目前有2种类型的二维码:
1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景
2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。
用户扫描带场景值二维码时,可能推送以下两种事件:
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。
获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。
生成临时二维码
package com.b505.QRcode;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import com.b505.entity.WechatQRCode;
import com.b505.util.Tool;
import com.b505.util.WeixinConstants;
import com.b505.util.WeixinUtil;
import net.sf.json.JSONObject;
/***
*
* 创建临时二维码
*
* @author
*
*/
public class TemporaryQRcode
{
/**
*
* @param accessToken 接口访问凭证
* @param expireSeconds 二维码有效时间 单位为秒 最长 1800秒 (30天)
* @param sceneId 场景id 临时二维码场景值Id为32位非0整数 永久二维码的场景值ID取1~10000
* 也就是说永久二维码一共可以创建10000个 临时的多
* @return
*/
public static WechatQRCode createForeverTicket(String accessToken, int expireSeconds, int sceneId)
{
WechatQRCode wechatQRCode = null;
// 拼接请求地址
String requestUrl = " https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
requestUrl = requestUrl.replace("TOKEN", accessToken);
// 需要提交json数据
String jsonmsg = "{\"expire_seconds\":%d,\"action_name\": \"QR_SCENE\",\"action_info\":{\"scene\":{\"scene_id\":%d}}}";
// 创建永久带参二维码
JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "POST", String.format(jsonmsg,expireSeconds, sceneId));
if (null != jsonObject)
{
System.out.println(jsonObject);
try
{
wechatQRCode=new WechatQRCode();
System.out.println(1);
wechatQRCode.setTicket(jsonObject.getString("ticket"));
wechatQRCode.setExpire_seconds(jsonObject.getInt("expire_seconds"));
System.out.println(2);
System.out.println("永久带参二维码ticket成功=" + wechatQRCode.getTicket()+"Expire_seconds="+wechatQRCode.getExpire_seconds());
} catch (Exception e)
{
wechatQRCode =null;
int err = jsonObject.getInt("errcode");
String errormsg = jsonObject.getString("errmsg");
System.out.println("永久带参二维码ticket失败失败errcode=" + err + "errmsg=" + errormsg);
}
}
return wechatQRCode;
}
public static void main(String[] args)
{ //获得token不再说明
String assesstoken = WeixinUtil.getAccessToken(WeixinConstants.APPID, WeixinConstants.APPSECRET).getToken();
WechatQRCode wechatQRCode =createForeverTicket(assesstoken, 900, 111111);
//临时二维码的 ticket
System.out.println(wechatQRCode.getTicket());
//临时二维码有效时间
System.out.println(wechatQRCode.getExpire_seconds());
String path = "d:/QRcode";
getRQcode(wechatQRCode.getTicket(), path);
}
public static String getRQcode(String ticket, String savepath)
{
String filepath = null;
String requestUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
requestUrl = requestUrl.replace("TICKET", Tool.urlencodeutf8(ticket));
try
{
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
if (!savepath.endsWith("/"))
{
savepath += "/";
}
// 将ticket 作为文件名
filepath = savepath + ticket + ".jpg";
// 将微信服务器返回的输入流写入文件
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
FileOutputStream fos = new FileOutputStream(new File(filepath));
byte[] buf = new byte[8096];
int size = 0;
while ((size = bis.read(buf)) != -1)
fos.write(buf, 0, size);
fos.close();
bis.close();
System.out.println(conn);
conn.disconnect();
System.out.println("根据ticket换取二维码成功");
} catch (Exception e)
{
filepath = null;
System.out.println("根据ticket换取二维码失败" + e);
}
return filepath;
}
}
package com.b505.util;
import java.awt.Menu;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.b505.pojo.*;
/**
*
* 公众平台通用接口工具类
* @author
*
*/
public class WeixinUtil
{
private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
/**
* 发起https请求并获取结果
*
* @param requestUrl 请求地址
* @param requestMethod 请求方式(GET、POST)
* @param outputStr 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new JEEWeiXinX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.fromObject(buffer.toString());
} catch (ConnectException ce) {
log.error("Weixin server connection timed out.");
} catch (Exception e) {
log.error("https request error:{}", e);
}
return jsonObject;
} }
createForeverTicket()方法返回值是WechatQRCode对象,他封装了ticket和expire_seconds参数。WechatQRCode类代码如下:
package com.b505.entity;
public class WechatQRCode
{
// 获取的二维码
private String ticket;
// 二维码的有效时间,单位为秒,最大不超过2592000(即30天)
private int expire_seconds;
set get ...省}
返回结果 创建成功
永久带参数二维码创建
跟上面大致一样,少的就是没有时间限制,
直接写出代码
package com.b505.QRcode;
import net.sf.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import com.b505.util.Tool;
import com.b505.util.WeixinConstants;
import com.b505.util.WeixinUtil;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
/**
* 二维码生成和读的工具类
*
*/
public class QRcode
{
/**
* 永久二维码
* @param accessToken
* @param sceneId场景iD 1~10000
* @return
*/
public static String createForeverTicket(String accessToken, int sceneId)
{
String ticke = null;
// 拼接请求地址
String requestUrl = " https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
requestUrl = requestUrl.replace("TOKEN", accessToken);
// 需要提交json数据
String jsonmsg = "{\"action_name\": \"QR_LIMIT_SCENE\",\"action_info\":{\"scene\":{\"scene_id\":%d}}}";
// 创建永久带参二维码
JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "POST", String.format(jsonmsg, sceneId));
if (null != jsonObject)
{
System.out.println(jsonObject);
try
{
ticke = jsonObject.getString("ticket");
System.out.println("永久带参二维码ticket成功=" + ticke);
} catch (Exception e)
{
int err = jsonObject.getInt("errcode");
String errormsg = jsonObject.getString("errmsg");
System.out.println("永久带参二维码ticket失败失败errcode=" + err + "errmsg=" + errormsg);
}
}
return ticke;
}
public static void main(String[] args)
{
String assesstoken = WeixinUtil.getAccessToken(WeixinConstants.APPID, WeixinConstants.APPSECRET).getToken();
String ticket = createForeverTicket(assesstoken, 617);
String path = "d:/QRcode";
getRQcode(ticket, path);
}
public static String getRQcode(String ticket, String savepath)
{
String filepath = null;
String requestUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
requestUrl = requestUrl.replace("TICKET", Tool.urlencodeutf8(ticket));
try
{
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
if (!savepath.endsWith("/"))
{
savepath += "/";
}
// 将ticket 作为文件名
filepath = savepath + ticket + ".jpg";
// 将微信服务器返回的输入流写入文件
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
FileOutputStream fos = new FileOutputStream(new File(filepath));
byte[] buf = new byte[8096];
int size = 0;
while ((size = bis.read(buf)) != -1)
fos.write(buf, 0, size);
fos.close();
bis.close();
System.out.println(conn);
conn.disconnect();
System.out.println("根据ticket换取二维码成功");
} catch (Exception e)
{
filepath = null;
System.out.println("根据ticket换取二维码失败" + e);
}
return filepath;
}
}
运行结果 可见成功
扫描带参数二维码事件
官方文档说过
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。
有人可能会问该怎么样才能执行这个时间呢?
用户扫描带场景值二维码时,可能推送以下两种事件:
实现代码如下 本人使用的是永久带参数二维码测试的,我设置的场景值ID为617
用户未关注时,进行关注后的事件推送 扫二维码,并关注,这个是事件类型是 subscribe ,之后传来的事件key值为"qrscene_617" ,就是 在ID前面加上了前缀
用户已关注时的事件推送 他发生的事件类型是SCAN ,之后直接传来事件key值为 "617"
下面代码看不懂的话那就去柳峰的博客学习学习。
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件类型
String eventType = requestMap.get("Event");
// 订阅 当用户未关注该公众号 则先关注
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
//
String eventKey = requestMap.get("EventKey");
System.out.println(eventKey);
//判断场景ID是否为qrscene_617
if(eventKey.equals("qrscene_617"))
{
respContent ="借书请扫书上二维码!!";
textMessage.setContent(respContent);
respMessage = MessageUtil.textMessageToXml(textMessage);
return respMessage;
}
}
else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
String eventKey = requestMap.get("EventKey");
System.out.println("AAAAAAAAAA="+eventKey);
if(Integer.parseInt(eventKey)==617)
{
respContent ="借书请扫书上二维码!!";
}
textMessage.setContent(respContent);
respMessage = MessageUtil.textMessageToXml(textMessage);
}
}
刚接触微信开发,欢迎各位前来交流。
本文章是从《微信公众平台应用开发》柳峰老师总结学习学的,老师的博客,书籍对我帮助很大,在此向老师表达谢意,谢谢老师!!!!