|
@@ -0,0 +1,328 @@
|
|
|
+package com.miaxis.wx.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.json.XML;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.miaxis.common.constant.Constants;
|
|
|
+import com.miaxis.common.core.domain.entity.UserInfo;
|
|
|
+import com.miaxis.common.utils.StringUtils;
|
|
|
+import com.miaxis.common.utils.wx.MessageUtil;
|
|
|
+import com.miaxis.feign.dto.WxMessageCusom;
|
|
|
+import com.miaxis.feign.service.IWxSendService;
|
|
|
+import com.miaxis.system.service.ISysUserService;
|
|
|
+import com.miaxis.user.service.IUserInfoService;
|
|
|
+import com.miaxis.wx.service.IWxGzhService;
|
|
|
+import com.miaxis.wx.service.IWxMessageEvenService;
|
|
|
+import com.miaxis.wx.service.WxService;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.io.IOUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.security.MessageDigest;
|
|
|
+import java.security.NoSuchAlgorithmException;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 微信公众号业务层
|
|
|
+ * @author wwl
|
|
|
+ * @version 1.0
|
|
|
+ * @date 2021/10/20 14:57
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class WxGzhServiceImpl implements IWxGzhService {
|
|
|
+
|
|
|
+ private final RedisTemplate redisTemplate;
|
|
|
+
|
|
|
+ private final IWxSendService wxSendService;
|
|
|
+
|
|
|
+ private final ISysUserService userService;
|
|
|
+
|
|
|
+ private final IUserInfoService userInfoService;
|
|
|
+
|
|
|
+ private final IWxMessageEvenService wxMessageEvenService;
|
|
|
+
|
|
|
+ private final WxService wxService;
|
|
|
+
|
|
|
+
|
|
|
+ @Value("${zzgzh.appid}")
|
|
|
+ private String appid;
|
|
|
+
|
|
|
+ @Value("${zzgzh.appSecret}")
|
|
|
+ private String secret;
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取微信公众号token
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public String getGzhToken() {
|
|
|
+ String token = "";
|
|
|
+ Integer expiresIn;
|
|
|
+ if (redisTemplate.hasKey(Constants.GZH_MESSAGE_TOKEN)){
|
|
|
+ token = (String)redisTemplate.opsForValue().get(Constants.GZH_MESSAGE_TOKEN);
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(token)|| notEffect(token)){
|
|
|
+ String result = wxSendService.getAccessToken("client_credential",appid,secret);
|
|
|
+ JSONObject json = JSONObject.parseObject(result);
|
|
|
+ token = json.getString("access_token");
|
|
|
+ expiresIn = 1800;
|
|
|
+// expiresIn = json.getIntValue("expires_in");
|
|
|
+// if (expiresIn <= 0){
|
|
|
+// expiresIn = 7000;
|
|
|
+// }
|
|
|
+
|
|
|
+ redisTemplate.opsForValue().set(Constants.GZH_MESSAGE_TOKEN,token,expiresIn, TimeUnit.SECONDS);
|
|
|
+ }
|
|
|
+
|
|
|
+ return token;
|
|
|
+ }
|
|
|
+
|
|
|
+ //判定是否失效
|
|
|
+ private boolean notEffect(String token) {
|
|
|
+ String res = wxSendService.userInfo( token, "ovKTX5-FKLF6_sgTtCIXpG_lz3PY", "zh_CN");
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(res);
|
|
|
+ return jsonObject.getString("unionid") ==null;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 微信推送消息处理
|
|
|
+ * @param request
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public String handlePublicMsg(HttpServletRequest request) {
|
|
|
+ try {
|
|
|
+ log.info("1....");
|
|
|
+ cn.hutool.json.JSONObject decryptMap = XML.toJSONObject(IOUtils.toString(request.getInputStream()));
|
|
|
+ cn.hutool.json.JSONObject jsonObjectData = decryptMap.getJSONObject("xml");
|
|
|
+
|
|
|
+
|
|
|
+ //cn.hutool.json.JSONObject jsonObjectData = new cn.hutool.json.JSONObject("{\"CreateTime\":1639474955,\"EventKey\":\"https://jpcj-h5.zzxcx.net\",\"ToUserName\":\"gh_628da25a95e5\",\"MsgType\":\"event\",\"MenuId\":442656773,\"Event\":\"VIEW\",\"FromUserName\":\"ovKTX50v7OAEPI_ERofpUvrNQCJU\"}");
|
|
|
+ log.info("2-----jsonObjectData------"+jsonObjectData);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //开发者微信号
|
|
|
+ String toUserName = jsonObjectData.getStr("ToUserName");
|
|
|
+ //发送方帐号(一个OpenID)
|
|
|
+ String fromUserName = jsonObjectData.getStr("FromUserName");
|
|
|
+ // 区分消息类型
|
|
|
+ String msgType = jsonObjectData.getStr("MsgType");
|
|
|
+ //获取用户信息
|
|
|
+// String userInfoResult = wxSendService.userInfo(this.getGzhToken(), fromUserName, "zh_CN");
|
|
|
+// JSONObject jsonObj = JSONObject.parseObject(userInfoResult);
|
|
|
+
|
|
|
+ // 普通消息
|
|
|
+ if (MessageUtil.MESSAGE_TEXT.equals(msgType)) { // 文本消息
|
|
|
+
|
|
|
+ } else if (MessageUtil.MESSAGE_IMAGE.equals(msgType)) { // 图片消息
|
|
|
+ log.info("2.2...");
|
|
|
+ return MessageUtil.initText(fromUserName, toUserName, "抱歉,暂时无法识别图片信息!");
|
|
|
+ }else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) { // 事件消息
|
|
|
+ log.info("3....");
|
|
|
+ String result = null ;
|
|
|
+ // 区分事件推送
|
|
|
+ String event = jsonObjectData.getStr("Event");
|
|
|
+ if (MessageUtil.MESSAGE_SUBSCRIBE.equals(event)) { // 关注事件 或 扫描二维码关注事件
|
|
|
+ log.info("3.1...");
|
|
|
+ String res = wxSendService.userInfo( this.getGzhToken(), fromUserName, "zh_CN");
|
|
|
+
|
|
|
+ //存在Ticket为扫码关注
|
|
|
+ if (org.apache.commons.lang3.StringUtils.isNotEmpty(jsonObjectData.getStr("Ticket"))){
|
|
|
+ log.info("3.1.2..");
|
|
|
+ result = MessageUtil.initText(fromUserName,toUserName," ");
|
|
|
+
|
|
|
+ }else {
|
|
|
+ result = MessageUtil.initText(fromUserName, toUserName, "欢迎关注金牌车教,您的学车好伙伴!");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return result;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ } else if (MessageUtil.MESSAGE_UNSUBSCRIBE.equals(event)) { // 取消订阅事件
|
|
|
+ // todo 处理取消订阅事件
|
|
|
+
|
|
|
+ } else if (MessageUtil.MESSAGE_SCAN.equals(event)) { // 已关注扫描二维码事件
|
|
|
+
|
|
|
+
|
|
|
+ } else if (MessageUtil.MESSAGE_LOCATION.equals(event)) { // 上报地理位置事件
|
|
|
+ // todo 处理上报地理位置事件
|
|
|
+
|
|
|
+ } else if (MessageUtil.MESSAGE_CLICK.equals(event)) { // 点击菜单拉取消息时的事件推送事件
|
|
|
+
|
|
|
+
|
|
|
+ } else if (MessageUtil.MESSAGE_VIEW.equals(event)) { // 点击菜单跳转链接时的事件推送
|
|
|
+ // todo 处理点击菜单跳转链接时的事件推送
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("处理微信公众号请求信息,失败", e);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ private void sendSchool(StringBuffer buffer, List<Map> schools,String fromUserName) {
|
|
|
+ if (schools.size() <= 10){
|
|
|
+ buffer.append("请选择驾校:").append("\n\n");
|
|
|
+ for (Map school : schools) {
|
|
|
+ String name = (String) school.get("name");
|
|
|
+ String code = (String) school.get("code");
|
|
|
+ buffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid=" + code + "&msgmenucontent=ok\">" + name + "</a>").append("\n");
|
|
|
+
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ int times = (schools.size()-1)/10+1;
|
|
|
+ for (int i =0; i< times-1; i++){
|
|
|
+ StringBuffer partBuffer =new StringBuffer();
|
|
|
+ if (i == 0){
|
|
|
+ partBuffer.append("请选择驾校:").append("\n\n");
|
|
|
+ }
|
|
|
+ for (int j =0; j< 10 ; j++){
|
|
|
+ Map school = schools.get(i*10+j);
|
|
|
+ String name = (String) school.get("name");
|
|
|
+ String code = (String) school.get("code");
|
|
|
+ partBuffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid=" + code + "&msgmenucontent="+name+"\">" + name + "</a>").append("\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ messageCustomSend(fromUserName,this.getGzhToken(),partBuffer.toString());
|
|
|
+ }
|
|
|
+ //最后一页做相应消息
|
|
|
+ for (int i = (times-1)*10; i< schools.size() ; i++){
|
|
|
+ Map school = schools.get(i);
|
|
|
+ String name = (String) school.get("name");
|
|
|
+ String code = (String) school.get("code");
|
|
|
+ buffer.append("<a href=\"weixin://bizmsgmenu?msgmenuid=" + code + "&msgmenucontent="+name+"\">" + name + "</a>").append("\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送客服消息
|
|
|
+ * @param fromUserName
|
|
|
+ * @param token
|
|
|
+ */
|
|
|
+ private void messageCustomSend(String fromUserName,String token,String content){
|
|
|
+
|
|
|
+ WxMessageCusom wxMessageCusom = new WxMessageCusom();
|
|
|
+ wxMessageCusom.setTouser(fromUserName);
|
|
|
+ wxMessageCusom.setMsgtype("text");
|
|
|
+ HashMap<String, Object> contentMap = new HashMap<>();
|
|
|
+ contentMap.put("content",content);
|
|
|
+ wxMessageCusom.setText(contentMap);
|
|
|
+ String send = wxSendService.messageCustomSend(token, wxMessageCusom);
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(send);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public JSONObject getJspapi(String url) {
|
|
|
+
|
|
|
+ //1、获取AccessToken
|
|
|
+ String gzhToken = this.getGzhToken();
|
|
|
+ //2、获取Ticket
|
|
|
+ String jsapiStr = wxService.getticket(gzhToken, "jsapi");
|
|
|
+ //3、时间戳和随机字符串
|
|
|
+// String nonce_str = RandomStringUtils.randomAlphanumeric(16);
|
|
|
+// long timestamp = System.currentTimeMillis()/1000;
|
|
|
+ JSONObject jsapiData = JSONObject.parseObject(jsapiStr);
|
|
|
+ String ticket= jsapiData.getString("ticket");
|
|
|
+ Map<String, String> ret = sign(ticket, "https://jpcj-h5.zzxcx.net/mini1");
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// //4、获取url
|
|
|
+// String str = "jsapi_ticket="+jsapiStr+"&noncestr="+nonce_str+"×tamp="+timestamp+"&url="+url;
|
|
|
+//
|
|
|
+// //6、将字符串进行sha1加密
|
|
|
+// String signature = SHA1Util.SHA1(str);
|
|
|
+ JSONObject resultJSONObject = new JSONObject();
|
|
|
+ resultJSONObject.put("ticket",ticket);
|
|
|
+ resultJSONObject.put("appId",appid);
|
|
|
+ resultJSONObject.put("timestamp",ret.get("timestamp"));
|
|
|
+ resultJSONObject.put("nonceStr",ret.get("nonceStr"));
|
|
|
+ resultJSONObject.put("signature",ret.get("signature"));
|
|
|
+ return resultJSONObject;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static Map<String, String> sign(String jsapi_ticket, String url) {
|
|
|
+ Map<String, String> ret = new HashMap<String, String>();
|
|
|
+ String nonce_str = create_nonce_str();
|
|
|
+ String timestamp = create_timestamp();
|
|
|
+ String string1;
|
|
|
+ String signature = "";
|
|
|
+
|
|
|
+ //注意这里参数名必须全部小写,且必须有序
|
|
|
+ string1 = "jsapi_ticket=" + jsapi_ticket +
|
|
|
+ "&noncestr=" + nonce_str +
|
|
|
+ "×tamp=" + timestamp +
|
|
|
+ "&url=" + url;
|
|
|
+ System.out.println(string1);
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ MessageDigest crypt = MessageDigest.getInstance("SHA-1");
|
|
|
+ crypt.reset();
|
|
|
+ crypt.update(string1.getBytes("UTF-8"));
|
|
|
+ signature = byteToHex(crypt.digest());
|
|
|
+ }
|
|
|
+ catch (NoSuchAlgorithmException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ catch (UnsupportedEncodingException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ ret.put("url", url);
|
|
|
+ ret.put("jsapi_ticket", jsapi_ticket);
|
|
|
+ ret.put("nonceStr", nonce_str);
|
|
|
+ ret.put("timestamp", timestamp);
|
|
|
+ ret.put("signature", signature);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String byteToHex(final byte[] hash) {
|
|
|
+ Formatter formatter = new Formatter();
|
|
|
+ for (byte b : hash)
|
|
|
+ {
|
|
|
+ formatter.format("%02x", b);
|
|
|
+ }
|
|
|
+ String result = formatter.toString();
|
|
|
+ formatter.close();
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String create_nonce_str() {
|
|
|
+ return UUID.randomUUID().toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String create_timestamp() {
|
|
|
+ return Long.toString(System.currentTimeMillis() / 1000);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|