【标题】微信-推送公众号扫码关注信息(附源码)
【前言】
最近在做一个需求,也是公众号常用的功能-《扫码点餐》。
在店铺桌子贴一张固定二维码,用户扫码后进入公众号窗口①,推送模板消息(点餐消息)给用户②。
① 用户已关注公众号,则到关注页面;已关注则直接进入公众号窗口。
② 使用openId和模板消息id推送信息给用户。
这样可以收集用户的openId,绑定店铺,后期也能推送其他模板消息、帮助用户和店铺静默开通会员卡等操作。
【概览】
一、实现步骤
2、服务器接入指南
3、接收事件推送
4、与3同
【概览】
二、部分代码:
1、qrauth_wx.jsp(显示二维码)
<noscript>
<h3 class="tips">您的浏览器不支持JavaScript,请更改浏览器参数!</h3>
</noscript>
<%
String key = "key_" + System.currentTimeMillis();
String url = QRauthAction.getQRCodeByCache(storeName);
session.setAttribute("xxx_eqcode_url_" + key, url);
%>
<div class="mydiv" id="opacity"></div>
<div style="margin: auto; width: 100%; padding: 0px;" id="ecode_div">
<img alt="二维码" src="<%=serviceUrl%>/qrauth_wx_img.jsp?key=<%=key%>&width=<%=width%>&height=<%=height%>" title="扫码关注" style="max-width: 600px; max-height: 600px;" id="qrCode" />
</div>
2、获取access_token:
/**
* TODO 请求微信获取token
*
* @param appId
* @return
*/
protected static String getAccess_token(String appId, String secret) {
String rs = null;
try {
String mainUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + secret;
rs = NetUtils.getHtmlSource(mainUrl, 5000);
JSONObject json = new JSONObject(rs);
return json.getString("access_token");
} catch (Exception e) {
LogUtils.error(rs, e);
return "";
}
}
3、生成二维码:
/**
* 创建二维码
*
* @param access_token
* @param qrCodeType
* @return
*/
public static String createQRCode(String access_token, String parames, String qrCodeType) {
try {
Json json = new Json();
JSONObject jsonObject = new JSONObject();
JSONObject jsonObject1 = new JSONObject();
if (StringUtils.isNotBlank(qrCodeType) && "1".equals(qrCodeType)) {
// 生成永久二维码
jsonObject1.put("scene_str", parames);
jsonObject.put("scene", jsonObject1);
json.add("action_name", "QR_LIMIT_STR_SCENE");
json.add("action_info", jsonObject);
} else {
jsonObject1.put("scene_str", parames);
jsonObject.put("scene", jsonObject1);
json.add("expire_seconds", String.valueOf(1000 * 60 * 60 * 24)); // 有效期:秒
json.add("action_name", "QR_STR_SCENE");
json.add("action_info", jsonObject);
}
String createRS = WeiXinNetUtil.postJsonDataToServer(WeiXinUrl.QRCODE_CREATE + "?access_token=" + access_token, json.toString());
LogUtils.debug(createRS);
JSONObject creJson = new JSONObject(createRS);
if (!creJson.has("url")) {
return null;
}
return creJson.getString("url");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
4、接收推送消息:
if ("event".equalsIgnoreCase(msgType)) {
String event = map.containsKey("Event") ? map.get("Event") : null;
if (event != null) {
String eventKey = map.containsKey("EventKey") ? map.get("EventKey") : null;
// 关注/取消关注事件:
if ("subscribe".equalsIgnoreCase(event)) {
if (StringUtils.isNotBlank(eventKey)) {
eventKey = eventKey.replaceAll("qrscene_", "");
Update update = new Update("Account");
update.setKey("storeName", eventKey);
update.setValue("openid", openId);
update.execute(true);
}
new WeiXinMethod().message_custom_send(openId, "感谢你的关注,我与你同在!!!");
SendMessageDing sendMessageDing = new SendMessageDing();
sendMessageDing.setTitle("用户关注公众号");
sendMessageDing.setLogType("微信");
sendMessageDing.setLogInfo("用户{" + openId + "}关注了公众号,绑定了{" + eventKey + "}账号");
sendMessageDing.sendAsyn();
}
if ("unsubscribe".equalsIgnoreCase(event)) {
String storeName = DBUtils.getString("select storeName from Account where openId=? limit 1 ", new String[] { openId });
SendMessageDing sendMessageDing = new SendMessageDing();
sendMessageDing.setTitle("取消关注公众号");
sendMessageDing.setLogType("微信");
sendMessageDing.setLogInfo("用户{" + openId + "}取消关注公众号,为{" + storeName + "}账号;");
sendMessageDing.sendAsyn();
DBUtils.execute("update Account set openId=null where openId=? ", new String[] { openId });
}
if ("scan".equalsIgnoreCase(event)) {
if (StringUtils.isNotBlank(eventKey)) {
eventKey = eventKey.replaceAll("qrscene_", "");
Update update = new Update("SYCM_Account");
update.setKey("storeName", eventKey);
update.setValue("openid", openId);
update.execute(true);
}
SendMessageDing sendMessageDing = new SendMessageDing();
sendMessageDing.setTitle("用户重新扫码进公众号");
sendMessageDing.setLogType("微信");
sendMessageDing.setLogInfo("用户{" + openId + "}已关注公众号,为{" + eventKey + "}账号!");
sendMessageDing.sendAsyn();
}
if ("click".equalsIgnoreCase(event)) {
// @-菜单点击,菜单id匹配:
if ("NIUCM_V1001_DOWN".equalsIgnoreCase(eventKey)) {
String msg = "地址:https://www.baidu.com/";
out.println(WeiXinMethod.getSendPlainMsgXml(openId, toUserId, msg));
}
}
}
}
5、推送模板消息给用户:
/**
* TODO 模板推送
*
* @param map
*
*/
public static boolean queueReminderPush(Map<String, Object> map) {
String openId = map.get("openId").toString();
if (openId == null)
return false;
String title = map.get("title") == null ? "" : map.get("title").toString();
String keyword1 = map.get("keyword1") == null ? "" : map.get("keyword1").toString();
String keyword2 = map.get("keyword2") == null ? "" : map.get("keyword2").toString();
String detailUrl = map.get("detailUrl") == null ? "" : map.get("detailUrl").toString();
String remark = map.get("remark") == null ? "" : map.get("remark").toString();
try {
String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + AccessTokenUtil.getTokenByDB();
Json json = new Json();
Json data = new Json();
json.add("template_id", WX_APP_TEMPLATE_ID);
json.add("url", detailUrl);
json.add("topcolor", "#000000");
json.add("touser", openId);
data.put("first", newWeixinJson(title));
data.put("keyword1", newWeixinJson(keyword1));// 商家名称
data.put("keyword2", newWeixinJson(keyword2));// 评测结果
data.put("remark", newWeixinJson(remark, "#993366"));
json.put("data", data);
String strRes = NetUtils.getHtmlSourcePost(url, json.toString());
LogUtils.debug(strRes);
JSONObject obj = new JSONObject(strRes);
if (obj.has("errcode") && !"0".equalsIgnoreCase(obj.getString("errcode"))) {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
三、附件-代码:
代码地址:https://download.csdn.net/download/qq_26599807/12107121 密码:lcl20200116
如遇代码不能用,麻烦给作者留言,百忙之中尽量给以回复。
Ⅰ、可能原因:
1、尚未更新地址(最后编辑:2020-01-19 14:13:11)
2、资源未审核通过,一个小时后重试
3、资源被和谐了
4、not other...
Ⅱ、代码说明:
1、SendMessageDing类为推送服务消息日志类,可忽略。
2、QRImageUtils和qrauth_wx_img.jsp是二维码java生成方式,可自行度娘。
3、类似DBUtils和Update的是数据库操作封装类,可使用自己项目传统方式。
4、CacheUtils缓存、StringUtils字符串判断及转型。
作者附言:如果本文章帮到了您,劳烦动动贵手点个赞,关注一下,谢谢^_^