原创 微信公众号推送图片实现
1绑定微信事件
@RestController
@RequestMapping(value = "/api/wechat")
@Api(value = "【微信相关接口】")
public class ApiWeChatController {
private static Logger logger = LoggerFactory.getLogger(ApiWeChatController.class);
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
@RequestMapping(value = "/checkSignature", produces = "text/html; charset=utf-8")
public String handlewechatPush(HttpServletRequest request, HttpServletResponse response) throws Exception {
boolean isGet = request.getMethod().equalsIgnoreCase("get");
if (isGet) {
// 微信加密签名
String signature = request.getParameter("signature");
// 随机字符串
String echostr = request.getParameter("echostr");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
logger.info("wx_check_signstrs:{},{},{},{}", signature, echostr, timestamp, nonce);
String[] str = { JsdConstants.WX_CHECKSIGN_TOKEN, timestamp, nonce };
Arrays.sort(str); // 字典序排序
String bigStr = str[0] + str[1] + str[2];
// SHA1加密,我这里用的是common-codec的jar包,你们也可以用java自带的消息消息摘要来写,只不过要多写几行代码,但结果都一样的
String digest = DigestUtils.sha1Hex(bigStr);
// 确认请求来至微信
if (digest.equals(signature)) {
return echostr;
}
return "";
} else {
// 处理接收消息
logger.info("Wechat event comes");
return handleWechatPushMessage(request, response);
}
}
private String handleWechatPushMessage(HttpServletRequest request, HttpServletResponse response) throws Exception {
WechatEventMessage eventMessage = dom4jXMLParse(request.getInputStream());
WechatMessageType msgType = null;
try {
msgType = WechatMessageType.valueOf(eventMessage.getMsgType().toUpperCase());
} catch (Exception e) {
logger.error("cannot resolve the wechat event type: {}", eventMessage.getMsgType(), e);
}
if (msgType == WechatMessageType.EVENT) {
// 处理事件
String event = eventMessage.getEvent().toUpperCase();
switch (event) {
case "CLICK": // 点击事件
return wechatClickEventHandler.handle(request, response, eventMessage);
case "SUBSCRIBE": // 关注
return wechatSubscribeEventHandler.handle(request, response, eventMessage);
case "UNSUBSCRIBE": // 取消关注
return wechatUnsubscribeEventHandler.handle(request, response, eventMessage);
case "SCAN": // 扫码
return wechatScanEventHandler.handle(request, response, eventMessage);
case "VIEW": // 菜单跳转
return JsdConstants.SUCCESS;
case "LOCATION": // 位置
return JsdConstants.SUCCESS;
default:
return JsdConstants.SUCCESS;
}
} else if (msgType == WechatMessageType.TEXT) {
return wechatTextAutoHandler.handle(request, response, eventMessage);
}
return JsdConstants.SUCCESS;
}
private static String encode(String str) {
if (str == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
messageDigest.update(str.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
// 把密文转换成十六进制的字符串形式
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
}
2点击事件处理器
@Service
public class WechatClickEventHandler {
private static Logger logger = LoggerFactory.getLogger(WechatClickEventHandler.class);
private ExecutorService pool = Executors.newFixedThreadPool(10);
@Autowired
UmsUserMapper userMapper;
@Autowired
RedisUtil redisUtil;
@Autowired
WeiXinUtil weiXinUtil;
@Autowired
APIUserService apiUserService;
@Autowired
PictureUtil pictureUtil;
public String handle(HttpServletRequest request, HttpServletResponse response, WechatEventMessage eventMessage) throws Exception {
String eventKey = eventMessage.getEventKey();
switch(eventKey){
case "DEEP_SAY": // 大道至简
pool.execute(new Runnable() {
@Override
public void run() {
try {
toSignIn(eventMessage.getFromUserName(), null);
} catch (Exception e) {
logger.error("toSignIn.error", e);
}
}
});
break;
}
return JsdConstants.SUCCESS;
}
public String toSignIn(String openid, String info) throws Exception {
logger.info("跳转到生成图片[openid]: {}", openid);
long nowtime = System.currentTimeMillis();
// 获取日期
String dateStr = DateFormatUtils.format(nowtime, JsdConstants.YMD2);
// 获取用户信息
Map<String, Object> param = new HashMap<>();
param.put("openid", openid);
param.put("subscribe", 1);
List<UmsUser> users = userMapper.selectBySelective(param);
if (users.isEmpty()) {
return JsdConstants.SUCCESS;
}
String imageTime = redisUtil.getHashKey("times", "image").toString();
String time = redisUtil.getHashKey("imageTimes", openid + dateStr);
if (time == null) {
redisUtil.put("musicTimes", openid + dateStr, "0");
} else if (Integer.parseInt(time) >= Integer.parseInt(imageTime)) {
weiXinUtil.sendText(openid, "今日已达获取上限");
return JsdConstants.SUCCESS;
}
UmsUser user = users.get(0);
long userId = user.getId();
// 当天底片
String baseUrl = JsdConstants.FILE_PATH + "/user/base/" + dateStr + ".png";
// 判断当天是否已有底片
File todayBase = new File(baseUrl);
if (!todayBase.exists()) {
String backUrl = redisUtil.getHashKey("imagebackurl", dateStr); // 获取今日背景图
if (backUrl == null) {
backUrl = JsdConstants.FILE_PATH + "/back/zhujian.png";
}
String festival = redisUtil.getHashKey("festivals", dateStr);
if (festival == null) {
festival = "";
}
String weekday = DateFormatUtils.format(nowtime, JsdConstants.YMD) + " " + CommonUtils.timeToWeek(nowtime) + " " + festival;
String solarTerm = redisUtil.getHashKey("solarTerms", dateStr);
if (solarTerm == null) {
solarTerm = "";
}
String lunar = LunarUtil.getLunarString() + " " + solarTerm;
logger.info("开始生成今日底片: {}", dateStr);
pictureUtil.overlapImage1(JsdConstants.FILE_PATH + "/basic/kb3.png", backUrl, weekday, lunar, baseUrl);
}
String txUrl = JsdConstants.FILE_PATH + "/basic/circle.jpg"; // 默认头像图片
// 头像可做缓存有效期
byte[] btImg = GetImageUtil.getImageFromNetByUrl(user.getHeadimgurl());
if (null != btImg && btImg.length > 100) {
txUrl = JsdConstants.FILE_PATH + "/user/headimg/" + userId + ".jpg";
GetImageUtil.writeImageToDisk(btImg, txUrl);
}
// 需要存储到服务器
String qrcodeUrl = JsdConstants.FILE_PATH + "/user/qrcode/" + userId + ".jpg";
File qrcodeImg = new File(qrcodeUrl);
if (!qrcodeImg.exists()) { // 未获取到用户专属二维码
qrcodeUrl = JsdConstants.FILE_PATH + "/basic/jsd.jpg";
}
if (info == null) {
info = redisUtil.getHashKey("wordInfos", dateStr);
if (info == null) {
info = redisUtil.getHashKey("wordInfos", JsdConstants.MAIN_OPENID);
}
}
if (info.length() > 200) {
info = info.substring(0, 200);
}
logger.info("开始生成用户专属图片 ");
String sendUrl = JsdConstants.FILE_PATH + "/user/image/" + dateStr + userId + ".png";
pictureUtil.overlapImage2(baseUrl, qrcodeUrl, JsdConstants.FILE_PATH + "/basic/xk52.jpg", txUrl, sendUrl, info);
JSONObject res = weiXinUtil.uploadFile(sendUrl, dateStr + userId + ".png", "image");
if(res != null){
JSONObject sendRs = weiXinUtil.sendImage(openid, res.getString("media_id"));
if (sendRs.getInt("errcode") != 0) { // 客服消息发送失败
weiXinUtil.sendText(JsdConstants.MAIN_OPENID, "客户图片发送失败");
} else {
redisUtil.increment("imageTimes", openid + dateStr, 1);
}
}
return "SUCCESS";
}
}
简单的实现完成
化繁为简,极致高效。
所有代码为本人原创,转载请联系本人。