為了滿足用戶渠道推廣分析和用戶帳號綁定等場景的需要,公眾平台提供了生成帶參數二維碼的接口。使用該接口可以獲得多個帶不同場景值的二維碼,用戶掃描后,公眾號可以接收到事件推送。
目前有2種類型的二維碼:
1、臨時二維碼,是有過期時間的,最長可以設置為在二維碼生成后的30天(即2592000秒)后過期,但能夠生成較多數量。臨時二維碼主要用於帳號綁定等不要求二維碼永久保存的業務場景 2、永久二維碼,是無過期時間的,但數量較少(目前為最多10萬個)。永久二維碼主要用於適用於帳號綁定、用戶來源統計等場景。
用戶掃描帶場景值二維碼時,可能推送以下兩種事件:
如果用戶還未關注公眾號,則用戶可以關注公眾號,關注后微信會將帶場景值關注事件推送給開發者。
如果用戶已經關注公眾號,在用戶掃描后會自動進入會話,微信也會將帶場景值掃描事件推送給開發者。
獲取帶參數的二維碼的過程包括兩步,首先創建二維碼ticket,然后憑借ticket到指定URL換取二維碼。
參數說明
| 參數 | 說明 |
|---|---|
| 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 |
返回說明
正確的Json返回結果:
| 參數 | 說明 |
|---|---|
| ticket | 獲取的二維碼ticket,憑借此ticket可以在有效時間內換取二維碼。 |
| expire_seconds | 該二維碼有效時間,以秒為單位。 最大不超過2592000(即30天)。 |
| url | 二維碼圖片解析后的地址,開發者可根據該地址自行生成需要的二維碼圖片 |
通過ticket換取二維碼
獲取二維碼ticket后,開發者可用ticket換取二維碼圖片。請注意,本接口無須登錄態即可調用。
請求說明
一、新建一個QrCodeUtil里面包含三個方法,分別是封裝請求的參數,產生二維碼和獲得二維碼
QrCodeUtil.java
package com.xu.wemall.components.weixin;
import com.alibaba.fastjson.JSONObject;
import com.xu.wemall.commons.constants.URIConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.TreeMap;
@Slf4j
@Component
public class QrCodeUtil {
@Autowired
private RestTemplate restTemplate;
@Autowired
private AccessTokenUtil accessTokenUtil;
private String createQrCodeString(String sceneStr) {
TreeMap<String, String> params = new TreeMap<>();
// output data
JSONObject data = new JSONObject();
data.put("action_name", "QR_SCENE");
data.put("expire_seconds", 3600);//一小時
JSONObject scene = new JSONObject();
scene.put("scene_str", sceneStr);
JSONObject actionInfo = new JSONObject();
actionInfo.put("scene", scene);
data.put("action_info", actionInfo);
return data.toJSONString();
}
public JSONObject createQrCode(String sceneId) {
String qrCodeString = this.createQrCodeString(sceneId);
log.info("qrCodeString:{}", qrCodeString);
String accessToken = accessTokenUtil.getAccessToken();
if (accessToken != null) {
log.info("URL{}", URIConstant.CREATE_QRCODE_URL);
String url = URIConstant.CREATE_QRCODE_URL.replace("ACCESS_TOKEN", accessToken);
log.info("URL_ACCESS_TOKEN:{}", url);
//將菜單對象轉換成JSON字符串
//發起POST請求創建菜單
JSONObject jsonObject = restTemplate.postForObject(url, qrCodeString, JSONObject.class);
return jsonObject;
}
return null;
}
public void showQrCode(String ticket) throws UnsupportedEncodingException {
String TICKET = URLEncoder.encode(ticket, "utf-8");
log.info("URL{}", URIConstant.SHOW_QRCODE_URL);
String url = URIConstant.SHOW_QRCODE_URL.replace("TICKET", TICKET);
log.info("SHOW_QRCODE_URL:{}", url);
//將菜單對象轉換成JSON字符串
//發起POST請求創建菜單
restTemplate.getForObject(url, JSONObject.class);
}
}
二、我們新建一個controller用來提交我們的請求
QrCodeWxController.java
package com.xu.wemall.controller.weixin;
import com.alibaba.fastjson.JSONObject;
import com.xu.wemall.components.weixin.QrCodeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.UnsupportedEncodingException;
/**
* 類名稱: LoginController
* 類描述: 與微信對接登陸驗證
*
* @author yuanjun
* 創建時間:2017年12月5日上午10:52:13
*/
@Slf4j
@RestController
@Api(tags = "微信生成帶參的二維碼接口")
@RequestMapping(value = "/weixin/qrcode")
public class QrCodeWxController {
@Autowired
private QrCodeUtil qrCodeUtil;
@ApiOperation(value = "創建帶參的二維碼")
@RequestMapping(value = "/createQrCode", method = RequestMethod.POST)
public Object createQrCode(String sceneId) {
JSONObject jsonObject = qrCodeUtil.createQrCode(sceneId);
return jsonObject;
}
@ApiOperation(value = "獲取帶參的二維碼")
@RequestMapping(value = "/showQrCode", method = RequestMethod.GET)
public void showQrCode(String ticket) throws UnsupportedEncodingException {
qrCodeUtil.showQrCode(ticket);
}
}
三、我們打開我們的swagger頁面提交一下請求試試看
四、根據ticket獲取二維碼
五、【One More Thing!!!】
那這個二維碼別人掃了我們怎么知道呢?回答:如果別人掃了我們生成的二維碼就會觸發我們的掃碼事件,微信服務器就會給我們推送如下的消息包
到這里你應該清楚了吧,我們在我們的微信對接接口的POST方法里增加如下代碼即可:
WeiXinController.java
package com.xu.wemall.controller.weixin;
import com.alibaba.fastjson.JSONObject;
import com.xu.wemall.commons.utils.CheckUtil;
import com.xu.wemall.components.weixin.MessageUtil;
import com.xu.wemall.components.weixin.WeiXinUserUtil;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Map;
/**
* 類名稱: LoginController
* 類描述: 與微信對接登陸驗證
*
* @author yuanjun
* 創建時間:2017年12月5日上午10:52:13
*/
@Slf4j
@RestController
@Api(tags = "接入驗證接口")
@RequestMapping(value = "/weChart")
public class WeiXinController {
@Autowired
private WeiXinUserUtil weiXinUserUtil;
@Autowired
private MessageUtil messageUtil;
@RequestMapping(value = "/connect", method = RequestMethod.GET)
public String connect(@RequestParam(value = "signature") String signature,
@RequestParam(value = "timestamp") String timestamp,
@RequestParam(value = "nonce") String nonce,
@RequestParam(value = "echostr") String echostr) {
log.info("-----開始校驗簽名-----");
PrintWriter out = null;
if (CheckUtil.checkSignature(signature, timestamp, nonce)) {
log.info("-----簽名校驗通過-----");
return echostr;
} else {
log.info("-----校驗簽名失敗-----");
return null;
}
}
@RequestMapping(value = "connect", method = RequestMethod.POST)
public String dopost(HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setCharacterEncoding("utf-8");
//將微信請求xml轉為map格式,獲取所需的參數
Map<String, String> map = MessageUtil.parseXml(request);
String ToUserName = map.get("ToUserName");
String FromUserName = map.get("FromUserName");
String MsgType = map.get("MsgType");
String Content = map.get("Content");
String Event = map.get("Event");
if(MessageUtil.REQ_MESSAGE_TYPE_EVENT.equals(MsgType)){
if(MessageUtil.EVENT_TYPE_SUBSCRIBE.equals(Event)){
String xmlString = messageUtil.subscribeForText(ToUserName,FromUserName);
//關注了公眾號,調用接口獲得用戶的詳細信息並保存到后台
JSONObject jsonObject = weiXinUserUtil.handdleWeixinUserInfo(FromUserName);
log.info("獲取用戶的詳細信息:{}",jsonObject.toJSONString());
return xmlString;
}else if(MessageUtil.EVENT_TYPE_UNSUBSCRIBE.equals(Event)){
String xmlString = messageUtil.unsubscribeForText(ToUserName,FromUserName);
return xmlString;
}else if(MessageUtil.EVENT_TYPE_SCAN.equals(Event)){
JSONObject jsonObject = weiXinUserUtil.handdleWeixinUserInfo(FromUserName);
log.info("獲取用戶的詳細信息:{}",jsonObject.toJSONString());
}
}
//處理文本類型,實現輸入1,回復相應的封裝的內容
if (MessageUtil.REQ_MESSAGE_TYPE_TEXT.equals(MsgType)) {
String xmlString = messageUtil.replyForText(ToUserName,FromUserName,"你發送的是:" + Content);
log.info(xmlString);
return xmlString;
}
if (MessageUtil.REQ_MESSAGE_TYPE_IMAGE.equals(MsgType)) {
String filePath = "C:\\Users\\RonnieXu\\Pictures\\2.jpg";
String xmlString = messageUtil.replyForImage(ToUserName,FromUserName,filePath);
return xmlString;
}
return null;
}
}
WeiXinUserUtil.java
package com.xu.wemall.components.weixin;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xu.wemall.commons.constants.URIConstant;
import com.xu.wemall.entry.WxUser;
import com.xu.wemall.service.IWxUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Slf4j
@Component
public class WeiXinUserUtil {
@Autowired
private IWxUserService iWxUserService;
@Autowired
private RestTemplate restTemplate;
@Autowired
private AccessTokenUtil accessTokenUtil;
public JSONObject handdleWeixinUserInfo(String openId) {
String accessToken = accessTokenUtil.getAccessToken();
if (accessToken != null) {
log.info("URL{}", URIConstant.OPENID_USERINFO_URL);
String url = URIConstant.OPENID_USERINFO_URL.replace("ACCESS_TOKEN", accessToken)
.replace("OPENID", openId);
log.info("OPENID_USERINFO_URL:{}", url);
//發起POST請求創建菜單
JSONObject jsonObject = restTemplate.getForObject(url, JSONObject.class);
//表示訂閱了該公眾號
if (jsonObject.getIntValue("subscribe") == 1) {
//保存
WxUser wxUser = JSONObject.parseObject(jsonObject.toJSONString(), WxUser.class);
//先查一下是否曾經查詢過(查看數據庫數據)
QueryWrapper<WxUser> queryWrapper = new QueryWrapper();
queryWrapper.lambda().eq(WxUser::getOpenid, openId);
WxUser wxUserExist = iWxUserService.getOne(queryWrapper);
if (wxUserExist == null) {
boolean result = iWxUserService.saveOrUpdate(wxUser);
}
}
return jsonObject;
}
return null;
}
}
打完收工,下回再見!
========================================================================================================================================================================================================
如果您覺得此文有幫助,可以小小打賞一下,持續更新更有動力喲!







