1.微信公众平台测试账号
我用内网穿透把本地的项目映射到外网,主要为了方便测试
在本地项目映射成功后可以扫一下“测试号二维码
”看是否正常进入到后台
2,添加参数获取场景二维码路径
首先通过上面得到的appID和appsecret获取到access_token
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
可以得到返回结果
{“access_token”:“ACCESS_TOKEN”,“expires_in”:7200}
官方文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
再通过access_token获取场景二维码的url参数
临时二维码可以自定义时间和永久二维码的请求路径都是:
http请求方式: POST
URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=ACCESS_TOKEN
重要的是参数,这也是场景二维码和其它二维码的区别,也就是scene:
当场景二维码需要携带的参数是数字类型:
{“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”: “abc”}}}
也就是说
QR_SCENE和QR_LIMIT_SCENE所匹配的是scene_id;
QR_STR_SCENE和QR_LIMIT_STR_SCENE所匹配的是scene_str;
可以得到返回值:
{“ticket”:“gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm
3sUw==”,“expire_seconds”:60,“url”:“http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI”}
其中ticket就是所需要的场景二维码的参数
官方文档:https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
通过 ticket 换取二维码
获取二维码 ticket 后,开发者可用 ticket 换取二维码图片。
HTTP GET请求:https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET (TICKET需要UrlEncode)
3.后台处理
对于关注,取消关注,再次扫码,点击等事件场景二维码都会返回到指定的后台路径(固定二维码,只能触发特定的操作比:已经关注后再次扫码就会直接登录进去不会再触发跳转后台路径)
代码示例:
// xml格式的消息数据
String respXml = null;
// 调用parseXml方法解析请求消息
Map<String, String> requestMap = MessageUtil.parseXml(request);
// 发送方帐号
String fromUserName = requestMap.get("FromUserName");
// 开发者微信号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
// 事件类型
//SCAN:已绑定(再次扫码触发),SUBSCRIBE:绑定,UNSUBSCRIBE:取消订阅,CLICK:点击事件
String eventType = requestMap.get("Event");
//从二维码传递过来的用户信息
//如果是第一次关注会在用户信息前默认加qrscene_
String id = requestMap.get("EventKey").replace("qrscene_", "");
页面显示:
<img class="qrcode lightBorder" src="https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket={{ticket}}" height="200" width="200">
请求获取ticket
package com.xxx.xxx.xxx;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Controller;
import net.sf.json.JSONObject;
@Controller
public class cs {
public static void main(String[] args) throws Exception {
Map<String, String> parameters1 = new HashMap<String, String>();
parameters1.put("grant_type", "client_credential");
parameters1.put("appid", "wx293af304e9325ff4");
parameters1.put("secret", "e3f569eab65224d7a360bce5648477bd");
String result1 = sendGet("https://api.weixin.qq.com/cgi-bin/token", parameters1);
JSONObject fromObject = JSONObject.fromObject(result1.toString());
String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + fromObject.get("access_token");
String sendPost = doPost(url,
"{\"expire_seconds\": 604800,\"action_name\":\"QR_STR_SCENE\",\"action_info\":{\"scene\":{\"scene_str\": \"0077ae677f6846bf9ee2fd31b2811312\"}}}");
System.out.println(sendPost);
}
/**
* 发送POST请求
* @param url目的地址
* @param parameters请求参数,String类型。
* @return 远程响应结果
*/
public static String doPost(String url, String params) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);// 创建httpPost
httpPost.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)");
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
String charSet = "UTF-8";
StringEntity entity = new StringEntity(params, charSet);
httpPost.setEntity(entity);
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpPost);
StatusLine status = response.getStatusLine();
int state = status.getStatusCode();
if (state == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
String jsonString = EntityUtils.toString(responseEntity);
return jsonString;
} else {
System.err.println("请求返回:" + state + "(" + url + ")");
}
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 发送GET请求
* @param url目的地址
* @param parameters请求参数,Map类型。
* @return 远程响应结果
*/
public static String sendGet(String url, Map<String, String> parameters) {
String result = "";// 返回的结果
BufferedReader in = null;// 读取响应输入流
StringBuffer sb = new StringBuffer();// 存储参数
String params = "";// 编码之后的参数
try {
// 编码请求参数
if (parameters.size() == 1) {
for (String name : parameters.keySet()) {
sb.append(name).append("=").append(parameters.get(name));
}
params = sb.toString();
} else {
for (String name : parameters.keySet()) {
sb.append(name).append("=").append(parameters.get(name)).append("&");
}
String temp_params = sb.toString();
params = temp_params.substring(0, temp_params.length() - 1);
}
String full_url = url + "?" + params;
// 创建URL对象
java.net.URL connURL = new java.net.URL(full_url);
// 打开URL连接
java.net.HttpURLConnection httpConn = (java.net.HttpURLConnection) connURL.openConnection();
// 设置通用属性
httpConn.setRequestProperty("Accept", "*/*");
httpConn.setRequestProperty("Connection", "Keep-Alive");
httpConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
// 建立实际的连接
httpConn.connect();
// 响应头部获取
Map<String, List<String>> headers = httpConn.getHeaderFields();
// 遍历所有的响应头字段
for (String key : headers.keySet()) {
System.out.println(key + "\t:\t" + headers.get(key));
}
// 定义BufferedReader输入流来读取URL的响应,并设置编码方式
in = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), "UTF-8"));
String line;
// 读取返回的内容
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}
/**
* 发送POST请求
* @param url 目的地址
* @param parameters 请求参数,Map类型。
* @return 远程响应结果
*/
public static String sendPost(String url, Map<String, String> parameters) {
String result = "";// 返回的结果
BufferedReader in = null;// 读取响应输入流
PrintWriter out = null;
StringBuffer sb = new StringBuffer();// 处理请求参数
String params = "";// 编码之后的参数
try {
// 编码请求参数
if (parameters.size() == 1) {
for (String name : parameters.keySet()) {
String aa=parameters.get(name);
sb.append(name).append("=").append(parameters.get(name)).append("&");
}
params = sb.toString();
} else {
for (String name : parameters.keySet()) {
String aa=parameters.get(name);
sb.append(name).append("=").append(parameters.get(name)).append("&");
}
String temp_params = sb.toString();
params = temp_params.substring(0, temp_params.length() - 1);
}
// 创建URL对象
java.net.URL connURL = new java.net.URL(url);
// 打开URL连接
java.net.HttpURLConnection httpConn = (java.net.HttpURLConnection) connURL
.openConnection();
// 设置通用属性
httpConn.setRequestProperty("Accept", "*/*");
httpConn.setRequestProperty("Connection", "Keep-Alive");
httpConn.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
// 设置POST方式
httpConn.setDoInput(true);
httpConn.setDoOutput(true);
// 获取HttpURLConnection对象对应的输出流
out = new PrintWriter(httpConn.getOutputStream());
// 发送请求参数
out.write(params);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应,设置编码方式
in = new BufferedReader(new InputStreamReader(httpConn
.getInputStream(), "UTF-8"));
String line;
// 读取返回的内容
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}