版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w_t_y_y/article/details/86668690
接着前面的博客进度。如现在再把扫描带参数二维码进入公众号的用户保存到数据库
一、临时二维码:
获取二维码需要先获取ticket,再用ticket来换图片。这里请求参数比较短,就不封装对象了,直接使用字符串拼接成json串。
1、方法一、使用scene_id获取ticket,建议使用这种方法:
(1)、先生成二维码加一张背景图的图片:
WechatUtil:
//生成临时二维码ticket scene_id json
private static final String QRCODE_TEMPORARY_TICKET_SCENE_ID = "{\"expire_seconds\": SECONDS, \"action_name\": \"QR_SCENE\", \"action_info\": {\"scene\": {\"scene_id\": SCENEID}}}";
//生成临时二维码ticket scene_str json
private static final String QRCODE_TEMPORARY_TICKET_SCENE_STR = "{\"expire_seconds\": SECONDS, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": SCENESTR}}}";
//生成临时二维码ticket 的url
private static final String QR_TEMPORARY_TICKET_URL= "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN";
//使用scene_id生成临时二维码ticket
public static QrTicket getTemporaryQRTicketBySceneId(String appId, String appSecert,
Long expireSeconds, Long sceneId){
AccessToken accessToken = getAccessToken(appId, appSecert);
String url = QR_TEMPORARY_TICKET_URL.replace("TOKEN", accessToken.getAccessToken());
String postJson = QRCODE_TEMPORARY_TICKET_SCENE_ID.replace("SECONDS", String.valueOf(expireSeconds))
.replace("SCENEID", String.valueOf(sceneId));
JSONObject res = HttpsUtil.httpRequest(url, "POST", postJson);
QrTicket qrTicket = new QrTicket();
qrTicket.setExpireSeconds((Integer) res.get("expire_seconds"));
qrTicket.setTicket(res.getString("ticket"));
qrTicket.setUrl("url");
return qrTicket;
}
/**
* 将二维码和背景图片拼装成新的分享图片
* @param shareImageUrl 分享背景图片的地址
* @param qrCodeUrl 二维码图片的地址
* @param content 文字内容
* @return base64 String 的图片
*/
public static String getQrImgUrl(String shareImageUrl, String qrCodeUrl, String content) {
try {
// 读取背景图片
BufferedImage bgImage = ImageIO.read(new URL(shareImageUrl));
// 读取二维码图片
BufferedImage qrCodeImage = ImageIO.read(new URL(qrCodeUrl));
// 创建一张原始图片
BufferedImage bgPicture = new BufferedImage(bgImage.getWidth(null), bgImage.getHeight(null), BufferedImage.TYPE_INT_RGB);
// 开启画图
Graphics2D g = bgPicture.createGraphics();
// 绘制背景图片
g.drawImage(bgImage, 0, 0, null);
// 设置目标重叠的混合处理方式和透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
// 580*790
int starX = bgImage.getWidth(null) * 45 / 580; // 二维码距背景图片X轴距离
int startY = bgImage.getHeight(null) * 480 / 790; // 二维码距背景图片Y轴距离
// 绘制二维码图片
g.drawImage(qrCodeImage, starX, startY, 124, 124, null);
// 绘制文字
// g.setColor(new Color(139,142,147));
// g.setFont(new Font("微软雅黑", Font.PLAIN, 18));
// g.drawString(content, starX, startY + 124 + 30);
g.dispose();
// 将合成的图片转为base64String
ByteArrayOutputStream compositeImageByte = new ByteArrayOutputStream();
ImageIO.write(bgPicture, "png", compositeImageByte);
//转换成base64串
String pngBase64 = new BASE64Encoder().encodeBuffer(compositeImageByte.toByteArray()).trim();
pngBase64 = "data:image/png;base64," + pngBase64.replaceAll("\n", "").replaceAll("\r", "");
System.out.println("create base64 image success");
return pngBase64;
} catch (Exception e) {
System.out.println("create base64 image error");
return null;
}
}
controller:
package com.demo.wechat.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSON;
import com.demo.wechat.domain.Message;
import com.demo.wechat.domain.QrTicket;
import com.demo.wechat.util.WebUtil;
import com.demo.wechat.util.WechatUtil;
@Controller
@RequestMapping("/index")
public class ViewController {
@Value(value="${app.secret}")
private String appSecert;
@Value(value="${app.id}")
private String appId;
private Long expireSeconds = 60000000L;
private Long sceneId = 666L;
private String backImgUrl = "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=977119715,3452693422&fm=26&gp=0.jpg";
//通过ticket获取二维码
private static final String QR_CODE_URL ="https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";
//根据scene_id生成临时二维码 返回页面
@GetMapping("/getQrCodeBySceneId")
public String goQrCodeBySceneId(){
return "code";
}
//根据scene_id生成临时二维码
@PostMapping("/getQrCodeBySceneId")
@ResponseBody
public String getQrCodeBySceneId(){
QrTicket qrTicket = WechatUtil.getTemporaryQRTicketBySceneId(appId, appSecert, expireSeconds,
sceneId);
String qrCodeUrl = QR_CODE_URL.replace("TICKET", qrTicket.getTicket());
String url = WechatUtil.getQrImgUrl(backImgUrl, qrCodeUrl, "扫描关注");
System.out.println("结果"+url);
return url;
}
}
前端:
applcation.properties设置:
#返回的前缀 目录对应src/main/webapp下
spring.mvc.view.prefix:/WEB-INF/view/
#返回的后缀
spring.mvc.view.suffix: .jsp
code.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="../assets/js/jquery-3.2.1.min.js"></script>
<script>
$(function(){
alert("hello");
$.post("getQrCodeBySceneId",function(data){
alert(data)
$("#shareImage").attr('src',data);
})
}
)
</script>
</head>
<body>
<div id="shareBody" >
<img id="shareImage" src="" />
<!--<canvas id="shareCanvas"></canvas>-->
</div>
</body>
</html>
在浏览器访问http://localhost:8080/wechat/index/getQrCodeBySceneId:
(2)、二维码扫描事件:
/**
* 处理微信消息
* @param request request
* @param reqMsg 请求消息
* @param respMsg 回复消息
* @param remoteIp remoteIp
*/
private void handleMessage(HttpServletRequest request, WechatMsg reqMsg, String remoteIp){
String type = reqMsg.getMsgType();
String fromUserName = reqMsg.getFromUserName();
String event = reqMsg.getEvent();
String eventKey = reqMsg.getEventKey();
//event事件开始
if(type.equals("event")){
//关注/取消关注公众号事件
WechatUser dbWechatUser = wechatUserService.getByOpenId(fromUserName);
if(dbWechatUser == null){
//还没有关注过
System.out.println("还没有关注过");
WechatUser wechatUser = new WechatUser();
wechatUser.setCreateTime(new Date());
wechatUser.setIsDelete(false);
wechatUser.setUpdateTime(new Date());
wechatUser.setUserOpenId(fromUserName);
wechatUserService.insert(wechatUser);
}
//扫描带参数二维码关注事件
if("subscribe".equals(event) && eventKey.startsWith("qrscene_")){
//去掉前缀
Long key = Long.valueOf(eventKey.replace("qrscene_", ""));
if(sceneId == key || sceneId.equals(key)){
System.out.println("扫描带参数二维码关注");
QrCodeUser dbQrCodeUser = qrCodeUserService.getByOpenId(fromUserName);
if(dbQrCodeUser == null){
//还没有记录过
QrCodeUser qrCodeUser = new QrCodeUser();
qrCodeUser.setCreateTime(new Date());
qrCodeUser.setIsDelete(false);
qrCodeUser.setOpenId(fromUserName);
qrCodeUser.setSceneId(String.valueOf(sceneId));
qrCodeUser.setUpdateTime(new Date());
qrCodeUserService.insert(qrCodeUser);
}
}
}
//扫描带参数二维码浏览(已关注)事件
if("SCAN".equals(event)){
Long key = Long.valueOf(eventKey);
if(sceneId == key || sceneId.equals(key)){
System.out.println(fromUserName+"扫描带参数二维码已经关注");
}
}
}
//event事件结束
}
2、方法二、使用scene_str获取ticket。这种方法只有在用户未关注二维码时会把str参数值带过来:
wechatUtil:
//使用scene_str生成临时二维码ticket
public static QrTicket getTemporaryQRTicketBySceneStr(String appId, String appSecert,
Long expireSeconds, String sceneStr){
AccessToken accessToken = getAccessToken(appId, appSecert);
String url = QR_TEMPORARY_TICKET_URL.replace("TOKEN", accessToken.getAccessToken());
String postJson = QRCODE_TEMPORARY_TICKET_SCENE_STR.replace("SECONDS", String.valueOf(expireSeconds))
.replace("SCENESTR", sceneStr);
JSONObject res = HttpsUtil.httpRequest(url, "POST", postJson);
QrTicket qrTicket = new QrTicket();
qrTicket.setExpireSeconds((Integer) res.get("expire_seconds"));
qrTicket.setTicket(res.getString("ticket"));
qrTicket.setUrl("url");
return qrTicket;
}
controller:
private String scendStr = "test";
//根据scene_str生成临时二维码 返回页面
@GetMapping("/getQrCodeBySceneStr")
public String goQrCodeBySceneStr(){
return "codeStr";
}
//根据scene_id生成临时二维码
@PostMapping("/getQrCodeBySceneStr")
@ResponseBody
public String getQrCodeBySceneStr(){
QrTicket qrTicket = WechatUtil.getTemporaryQRTicketBySceneStr(appId, appSecert,
expireSeconds, scendStr);
String qrCodeUrl = QR_CODE_URL.replace("TICKET", qrTicket.getTicket());
String url = WechatUtil.getQrImgUrl(backImgUrl, qrCodeUrl, "扫描关注");
System.out.println("结果"+url);
return url;
}
消息:
二、永久二维码