Java微信开发——生成带参数的二维码以及扫描带参数二维码事件

目前有2种类型的二维码:

1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于帐号绑定等不要求二维码永久保存的业务场景
2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于帐号绑定、用户来源统计等场景。

用户扫描带场景值二维码时,可能推送以下两种事件:

如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。

如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。


Java微信开发——生成带参数的二维码以及扫描带参数二维码事件_第1张图片

生成临时二维码

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;

	}
}
附加httpRequest()方法
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;

	}

}

运行结果   可见成功


扫描带参数二维码事件

官方文档说过

如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。

如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。

有人可能会问该怎么样才能执行这个时间呢?

用户扫描带场景值二维码时,可能推送以下两种事件:

  1. 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
  2. 如果用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者。  

Java微信开发——生成带参数的二维码以及扫描带参数二维码事件_第2张图片

Java微信开发——生成带参数的二维码以及扫描带参数二维码事件_第3张图片

实现代码如下      本人使用的是永久带参数二维码测试的,我设置的场景值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);  
                	}
				}

刚接触微信开发,欢迎各位前来交流。

本文章是从《微信公众平台应用开发》柳峰老师总结学习学的,老师的博客,书籍对我帮助很大,在此向老师表达谢意,谢谢老师!!!!

你可能感兴趣的:(微信开发,生成带参数的二维码)