ps:微信相关开发博客地址:https://www.cnblogs.com/txw1958/p/
本文介绍在微信公众平台上如何使用高级接口开发生成带参数二维码的功能。
为了满足用户渠道推广分析的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。
目前有2种类型的二维码,分别是临时二维码和永久二维码,前者有过期时间,最大为1800秒,但能够生成较多数量,后者无过期时间,数量较少(目前参数只支持1--100000)。两种二维码分别适用于帐号绑定、用户来源统计等场景。
用户扫描带场景值二维码时,可能推送以下两种事件:
如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。
如果用户已经关注公众号,在用户扫描后会自动进入会话,微信也会将带场景值扫描事件推送给开发者。
获取带参数的二维码的过程包括两步,首先创建二维码ticket,然后凭借ticket到指定URL换取二维码。
// 临时二维码
private final static String QR_SCENE = "QR_SCENE";
// 永久二维码
private final static String QR_LIMIT_SCENE = "QR_LIMIT_SCENE";
// 永久二维码(字符串)
private final static String QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE";
// 创建二维码
private String create_ticket_path = "https://api.weixin.qq.com/cgi-bin/qrcode/create";
// 通过ticket换取二维码
private static String showqrcode_path = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";
/**
* 创建永久二维码(字符串)
* @param sceneStr 场景值
* @param accessToken
* @return
*/
public static Map createForeverStrQr(String sceneStr,String accessToken ) {
RestTemplate rest = new RestTemplate();
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken ;
// 参数:{"action_name": "QR_LIMIT_STR_SCENE", "action_info": {"scene": {"scene_str": sceneStr}}}
Map
param.put("action_name", "QR_LIMIT_STR_SCENE");
Map
action.put("pId", "");
Map
scene.put("scene_str", sceneStr);
action.put("scene", scene);
param.put("action_info", action);
MultiValueMap
HttpEntity requestEntity = new HttpEntity(param, headers);
Map result = null;
try {
ResponseEntity
/**
* 创建临时带参数二维码
* @param accessToken
* @expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
* @param sceneId 场景Id
* @return
*/
public static String createTempQr(String accessToken, String expireSeconds, String sceneStr) {
RestTemplate rest = new RestTemplate();
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken ;
// 参数:{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}
Map
intMap.put("scene_str",sceneStr);
Map
mapMap.put("scene", intMap);
Map
paramsMap.put("expire_seconds", expireSeconds);
paramsMap.put("action_name", QR_SCENE);
paramsMap.put("action_info", mapMap);
MultiValueMap
HttpEntity requestEntity = new HttpEntity(paramsMap, headers);
Map result = null;
try {
ResponseEntity
/**
* 获取access_token
* @param appid 凭证
* @param appsecret 密钥
* @return
*/
public static String getAccessToken() {
String result = HttpRequestUtil.getAccessToken(WhParamesAPI.WX_APPID,WhParamesAPI.WX_SECRET);
try {
JSONObject jsonObject = JSONObject.parseObject(result);
String accessToken = (String) jsonObject.get("access_token");
return accessToken;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
//打印二维码地址
System.out.println(showqrcode_path+createTempQr(getAccessToken(),"2592000","o3Y6l1As68lzErl8jmOxhta8uhLg"));
}
/**
* HttpRequestUtil 工具类
*
*/
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import com.thinkgem.jeesite.common.utils.StringUtils;
import com.thinkgem.jeesite.common.utils.wechat.MyX509TrustManager;
public class HttpRequestUtil {
//private static Logger logger = Logger.getLogger(HttpRequestUtil.class);
public static final String GET_METHOD = "GET";
public static final String POST_METHOD = "POST";
public static final String DEFAULT_CHARSET = "utf-8";
private static int DEFAULT_CONNTIME = 5000;
private static int DEFAULT_READTIME = 5000;
// 获取access_token的路径
private static String token_path = "https://api.weixin.qq.com/cgi-bin/token";
/**
* http请求
*
* @param method
* 请求方法GET/POST
* @param path
* 请求路径
* @param timeout
* 连接超时时间 默认为5000
* @param readTimeout
* 读取超时时间 默认为5000
* @param data 数据
* @return
*/
public static String defaultConnection(String method, String path, int timeout, int readTimeout, String data)
throws Exception {
String result = "";
URL url = new URL(path);
if (url != null) {
HttpURLConnection conn = getConnection(method, url);
conn.setConnectTimeout(timeout == 0 ? DEFAULT_CONNTIME : timeout);
conn.setReadTimeout(readTimeout == 0 ? DEFAULT_READTIME : readTimeout);
if (data != null && !"".equals(data)) {
OutputStream output = conn.getOutputStream();
output.write(data.getBytes(DEFAULT_CHARSET));
output.flush();
output.close();
}
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream input = conn.getInputStream();
result = inputToStr(input);
input.close();
conn.disconnect();
}
}
return result;
}
/**
* 根据url的协议选择对应的请求方式 例如 http://www.baidu.com 则使用http请求,https://www.baidu.com
* 则使用https请求
*
* @param method
* 请求的方法
* @return
* @throws IOException
*/
private static HttpURLConnection getConnection(String method, URL url) throws IOException {
HttpURLConnection conn = null;
if ("https".equals(url.getProtocol())) {
SSLContext context = null;
try {
context = SSLContext.getInstance("SSL", "SunJSSE");
context.init(new KeyManager[0], new TrustManager[] { new MyX509TrustManager() },
new java.security.SecureRandom());
} catch (Exception e) {
throw new IOException(e);
}
HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection();
connHttps.setSSLSocketFactory(context.getSocketFactory());
connHttps.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
conn = connHttps;
} else {
conn = (HttpURLConnection) url.openConnection();
}
conn.setRequestMethod(method);
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
return conn;
}
/**
* 将输入流转换为字符串
*
* @param input
* 输入流
* @return 转换后的字符串
*/
public static String inputToStr(InputStream input) {
String result = "";
if (input != null) {
byte[] array = new byte[1024];
StringBuffer buffer = new StringBuffer();
try {
for (int index; (index = (input.read(array))) > -1;) {
buffer.append(new String(array, 0, index, DEFAULT_CHARSET));
}
result = buffer.toString();
} catch (IOException e) {
e.printStackTrace();
result = "";
}
}
return result;
}
/**
* 设置参数
*
* @param map
* 参数map
* @param path
* 需要赋值的path
* @param charset
* 编码格式 默认编码为utf-8(取消默认)
* @return 已经赋值好的url 只需要访问即可
*/
public static String setParmas(Map
String result = "";
boolean hasParams = false;
if (path != null && !"".equals(path)) {
if (map != null && map.size() > 0) {
StringBuilder builder = new StringBuilder();
Set
for (Entry
String key = entry.getKey().trim();
String value = entry.getValue().trim();
if (hasParams) {
builder.append("&");
} else {
hasParams = true;
}
if(charset != null && !"".equals(charset)){
//builder.append(key).append("=").append(URLDecoder.(value, charset));
builder.append(key).append("=").append(urlEncode(value, charset));
}else{
builder.append(key).append("=").append(value);
}
}
result = builder.toString();
}
}
return doUrlPath(path, result).toString();
}
/**
* 设置连接参数
*
* @param path
* 路径
* @return
*/
private static URL doUrlPath(String path, String query) throws Exception {
URL url = new URL(path);
if (StringUtils.isEmpty(path)) {
return url;
}
if (StringUtils.isEmpty(url.getQuery())) {
if (path.endsWith("?")) {
path += query;
} else {
path = path + "?" + query;
}
} else {
if (path.endsWith("&")) {
path += query;
} else {
path = path + "&" + query;
}
}
return new URL(path);
}
/**
* 默认的http请求执行方法,返回
*
* @param method
* 请求的方法 POST/GET
* @param path
* 请求path 路径
* @param map
* 请求参数集合
* @param data
* 输入的数据 允许为空
* @return
*/
public static String HttpDefaultExecute(String method, String path, Map
String result = "";
try {
String url = setParmas((TreeMap
result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 默认的https执行方法,返回
*
* @param method
* 请求的方法 POST/GET
* @param path
* 请求path 路径
* @param map
* 请求参数集合
* @param data
* 输入的数据 允许为空
* @return
*/
public static String HttpsDefaultExecute(String method, String path, Map
String result = "";
try {
String url = setParmas((TreeMap
result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取授权token
*
* @param key 应用key
* @param secret 应用密匙
* @return json格式的字符串
*/
public static String getAccessToken(String key, String secret) {
TreeMap
map.put("grant_type", "client_credential");
map.put("appid", key);
map.put("secret", secret);
String result = HttpDefaultExecute(GET_METHOD, token_path, map, "");
return result;
}
public static String urlEncode(String source, String encode) {
String result = source;
try {
result = URLEncoder.encode(source, encode);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}