原创 微信公众号推送图片实现

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";	
}
}

简单的实现完成

posted @ 2021-06-08 09:47  cris's  阅读(329)  评论(0编辑  收藏  举报