微信公眾號開發之生成帶參數的二維碼(六)


為了滿足用戶渠道推廣分析和用戶帳號綁定等場景的需要,公眾平台提供了生成帶參數二維碼的接口。使用該接口可以獲得多個帶不同場景值的二維碼,用戶掃描后,公眾號可以接收到事件推送。

目前有2種類型的二維碼:

1、臨時二維碼,是有過期時間的,最長可以設置為在二維碼生成后的30天(即2592000秒)后過期,但能夠生成較多數量。臨時二維碼主要用於帳號綁定等不要求二維碼永久保存的業務場景 2、永久二維碼,是無過期時間的,但數量較少(目前為最多10萬個)。永久二維碼主要用於適用於帳號綁定、用戶來源統計等場景。

用戶掃描帶場景值二維碼時,可能推送以下兩種事件:

如果用戶還未關注公眾號,則用戶可以關注公眾號,關注后微信會將帶場景值關注事件推送給開發者。

如果用戶已經關注公眾號,在用戶掃描后會自動進入會話,微信也會將帶場景值掃描事件推送給開發者。

獲取帶參數的二維碼的過程包括兩步,首先創建二維碼ticket,然后憑借ticket到指定URL換取二維碼。

http請求方式: POST
URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
POST數據格式:json
POST數據例子:{"expire_seconds": 604800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}}

或者也可以使用以下POST數據創建字符串形式的二維碼參數:
{"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "test"}}}

參數說明

參數 說明
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":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm
3sUw==","expire_seconds":60,"url":"http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI"}
參數 說明
ticket 獲取的二維碼ticket,憑借此ticket可以在有效時間內換取二維碼。
expire_seconds 該二維碼有效時間,以秒為單位。 最大不超過2592000(即30天)。
url 二維碼圖片解析后的地址,開發者可根據該地址自行生成需要的二維碼圖片

通過ticket換取二維碼

獲取二維碼ticket后,開發者可用ticket換取二維碼圖片。請注意,本接口無須登錄態即可調用。

請求說明

HTTP GET請求(請使用https協議)https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET
提醒:TICKET記得進行UrlEncode

 一、新建一個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獲取二維碼

https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQEd7zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyYlo5NXRyR0ljZ2oxOFVkZHh1MWQAAgQofw1eAwQQDgAA

五、【One More Thing!!!】

那這個二維碼別人掃了我們怎么知道呢?回答:如果別人掃了我們生成的二維碼就會觸發我們的掃碼事件,微信服務器就會給我們推送如下的消息包

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[FromUser]]></FromUserName>
  <CreateTime>123456789</CreateTime>
  <MsgType><![CDATA[event]]></MsgType>
  <Event><![CDATA[SCAN]]></Event>
  <EventKey><![CDATA[SCENE_VALUE]]></EventKey>
  <Ticket><![CDATA[TICKET]]></Ticket>
</xml> 

到這里你應該清楚了吧,我們在我們的微信對接接口的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;
}

}

打完收工,下回再見!

========================================================================================================================================================================================================

如果您覺得此文有幫助,可以小小打賞一下,持續更新更有動力喲!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM