|
@@ -0,0 +1,167 @@
|
|
|
+package vip.xiaonuo.biz.modular.api.service;
|
|
|
+
|
|
|
+import cn.hutool.core.util.ObjectUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import jakarta.annotation.Resource;
|
|
|
+import jakarta.servlet.http.HttpServletRequest;
|
|
|
+import jakarta.servlet.http.HttpServletResponse;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import vip.xiaonuo.biz.modular.officialinfo.entity.OfficialInfo;
|
|
|
+import vip.xiaonuo.biz.modular.officialinfo.service.OfficialInfoService;
|
|
|
+import vip.xiaonuo.biz.modular.utils.MsgUtil;
|
|
|
+import vip.xiaonuo.biz.modular.utils.XmlUtil;
|
|
|
+import vip.xiaonuo.common.exception.CommonException;
|
|
|
+import vip.xiaonuo.common.prop.CommonProperties;
|
|
|
+
|
|
|
+import java.io.PrintWriter;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class ApiService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private OfficialInfoService officialInfoService;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private CommonProperties commonProperties;
|
|
|
+
|
|
|
+ public static JSONObject wx_token_map = new JSONObject();
|
|
|
+
|
|
|
+ public void officialCallback(HttpServletRequest request, HttpServletResponse response) {
|
|
|
+ // 响应消息
|
|
|
+ PrintWriter out = null;
|
|
|
+ String resMessage = "";
|
|
|
+ try {
|
|
|
+ request.setCharacterEncoding("UTF-8");
|
|
|
+ response.setCharacterEncoding("UTF-8");
|
|
|
+ //把微信返回的xml信息转义成map
|
|
|
+ Map<String, Object> map = XmlUtil.parseXML(request.getInputStream());
|
|
|
+ //消息来源用户标识
|
|
|
+ String fromUserName = (String) map.get("FromUserName");
|
|
|
+ //消息目的用户标识
|
|
|
+ String toUserName = (String) map.get("ToUserName");
|
|
|
+ //消息创建时间(整型)
|
|
|
+ String createTime = (String) map.get("CreateTime");
|
|
|
+ //消息类型
|
|
|
+ String msgType = (String) map.get("MsgType");
|
|
|
+ //事件类型:subscribe/unsubscribe
|
|
|
+ String eventType = (String) map.get("Event");
|
|
|
+ //如果为事件类型
|
|
|
+ if (MsgUtil.MSGTYPE_EVENT.equals(msgType)) {
|
|
|
+ //查询是否存在公众号表记录
|
|
|
+ QueryWrapper<OfficialInfo> queryWrapper = new QueryWrapper<>();
|
|
|
+ queryWrapper.lambda().eq(OfficialInfo::getOfficialOpenId, fromUserName)
|
|
|
+ .last("limit 1");
|
|
|
+ OfficialInfo officialInfo = officialInfoService.getOne(queryWrapper);
|
|
|
+ if (officialInfo == null) {
|
|
|
+ officialInfo = new OfficialInfo();
|
|
|
+ JSONObject jsonObject = this.getUserInfo(fromUserName);
|
|
|
+ if (jsonObject != null) {
|
|
|
+ officialInfo.setWxAddress(jsonObject.getString("country")
|
|
|
+ + jsonObject.getString("province")
|
|
|
+ + jsonObject.getString("city"));
|
|
|
+ officialInfo.setCreateTime(new Date());
|
|
|
+ officialInfo.setNickName(jsonObject.getString("nickname"));
|
|
|
+ officialInfo.setOfficialOpenId(jsonObject.getString("openid"));
|
|
|
+ officialInfo.setUnionId(jsonObject.getString("unionid"));
|
|
|
+ officialInfo.setWxHead(jsonObject.getString("headimgurl"));
|
|
|
+ officialInfoService.save(officialInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //处理订阅事件-关注与取消关注
|
|
|
+ if (MsgUtil.MESSAGE_SUBSCIBE.equals(eventType)) {
|
|
|
+ officialInfo.setStatus(1);
|
|
|
+ System.out.println("您好,谢谢您的关注!!");
|
|
|
+ if (ObjectUtil.isEmpty(officialInfo.getUnionId())) {
|
|
|
+ JSONObject jsonObject = this.getUserInfo(fromUserName);
|
|
|
+ if (jsonObject != null) {
|
|
|
+ officialInfo.setUnionId(jsonObject.getString("unionid"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ resMessage = MsgUtil.subscribeForText(toUserName, fromUserName, "您好,谢谢您的关注!!");
|
|
|
+ } else if (MsgUtil.MESSAGE_UNSUBSCIBE.equals(eventType)) {//取消订阅
|
|
|
+ officialInfo.setStatus(0);
|
|
|
+ resMessage = MsgUtil.unsubscribeForText(toUserName, fromUserName, "取消关注~");
|
|
|
+ }
|
|
|
+ officialInfoService.updateById(officialInfo);
|
|
|
+ log.info("eventType:" + eventType + ",fromUserName:" + fromUserName + ",toUserName:" + toUserName + ",msgType:" + msgType + ",createTime:" + createTime);
|
|
|
+ }
|
|
|
+ out = response.getWriter();
|
|
|
+ out.println(resMessage);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ log.info("公众号回调异常------", e.getMessage());
|
|
|
+ //itemErrorInfoService.errorAdd(e);
|
|
|
+ } finally {
|
|
|
+ if (out != null) {
|
|
|
+ out.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 微信公众号的appid以及sercet
|
|
|
+ *
|
|
|
+ * @param openId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private JSONObject getUserInfo(String openId) {
|
|
|
+ JSONObject jsonObject = null;
|
|
|
+ String accessToken = getAccessToken(commonProperties.getOfficialAppId(), commonProperties.getOfficialSecret());
|
|
|
+ log.info("-------openId:" + openId + "-------");
|
|
|
+ log.info("-------accessToken:" + accessToken + "-------");
|
|
|
+ StringBuffer url = new StringBuffer("https://api.weixin.qq.com/cgi-bin/user/info");
|
|
|
+ url.append("?access_token=").append(accessToken);
|
|
|
+ url.append("&openid=").append(openId);
|
|
|
+ url.append("&lang=zh_CN");
|
|
|
+
|
|
|
+ String content = HttpUtil.get(url.toString());
|
|
|
+ if (ObjectUtil.isNotEmpty(content)) {
|
|
|
+ jsonObject = JSONObject.parseObject(content);
|
|
|
+ }
|
|
|
+ log.info("-------微信用户信息:" + content + "-------");
|
|
|
+ return jsonObject;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private String getAccessToken(String sAppid, String sSecret) {
|
|
|
+ // 因为微信有限制次数跟有效期,所以需要存在redis中
|
|
|
+ if (wx_token_map.size() == 0) {
|
|
|
+ wx_token_map.put("token", null);
|
|
|
+ }
|
|
|
+ String token = wx_token_map.getString("token");
|
|
|
+ // token失效或者为空
|
|
|
+ if (StrUtil.isEmpty(token) || "null".equals(token)) {
|
|
|
+ StringBuffer url = new StringBuffer("https://api.weixin.qq.com/cgi-bin/token");
|
|
|
+ url.append("?grant_type=client_credential");
|
|
|
+ url.append("&appid=").append(sAppid);
|
|
|
+ url.append("&secret=").append(sSecret);
|
|
|
+ log.info(url.toString());
|
|
|
+ String content = HttpUtil.get(url.toString());
|
|
|
+ if (StrUtil.isEmpty(content) || !content.contains("access_token")) {
|
|
|
+ log.info(content);
|
|
|
+ throw new CommonException("获取公众号accessToken失败");
|
|
|
+ }
|
|
|
+ token = JSONObject.parseObject(content).getString("access_token");
|
|
|
+ // 设置为1.9h(有效期2h)
|
|
|
+ wx_token_map.put("token", token);
|
|
|
+ wx_token_map.put("time", System.currentTimeMillis());
|
|
|
+ } else {
|
|
|
+ Long time = wx_token_map.getLong("time");
|
|
|
+ long l = System.currentTimeMillis();
|
|
|
+ if ((l - time) >= 1.9 * 3600 * 1000) {
|
|
|
+ wx_token_map.clear();
|
|
|
+ getAccessToken(sAppid, sSecret);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return token;
|
|
|
+ }
|
|
|
+}
|