You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

424 lines
18 KiB

  1. package com.iformall.controller;
  2. import com.google.gson.JsonArray;
  3. import com.google.gson.JsonElement;
  4. import com.google.gson.JsonObject;
  5. import com.iformall.controller.base.BaseController;
  6. import com.iformall.domain.po.WxAppinfo;
  7. import com.iformall.domain.po.WxComponentVerifyTicket;
  8. import com.iformall.domain.po.WxWeappAuditStatus;
  9. import com.iformall.enums.EnumAppType;
  10. import com.iformall.enums.EnumWeappAuditStatus;
  11. import com.iformall.service.*;
  12. import com.iformall.service.toutiao.FmTtOpenService;
  13. import com.iformall.service.toutiao.api.bean.TtOpenNotifyMsg;
  14. import com.iformall.utils.DateUtils;
  15. import io.swagger.annotations.Api;
  16. import io.swagger.annotations.ApiOperation;
  17. import me.chanjar.weixin.common.error.WxErrorException;
  18. import me.chanjar.weixin.common.util.json.GsonHelper;
  19. import org.apache.commons.lang3.StringUtils;
  20. import org.slf4j.Logger;
  21. import org.slf4j.LoggerFactory;
  22. import org.springframework.beans.factory.annotation.Autowired;
  23. import org.springframework.stereotype.Controller;
  24. import org.springframework.web.bind.annotation.*;
  25. import reactor.core.publisher.Flux;
  26. import javax.servlet.http.HttpServletRequest;
  27. import javax.servlet.http.HttpServletResponse;
  28. import java.io.IOException;
  29. import java.io.PrintWriter;
  30. import java.text.SimpleDateFormat;
  31. import java.util.Date;
  32. import java.util.Map;
  33. @Controller
  34. @RequestMapping("/ttOpen")
  35. @Api(description = "头条第三方开放平台回调相关接口")
  36. public class TtCalllbackController extends BaseController {
  37. private final Logger logger = LoggerFactory.getLogger(this.getClass());
  38. @Autowired
  39. protected FmTtOpenService openService;
  40. @Autowired
  41. private WxComponentVerifyTicketService componentVerifyTicketService;
  42. @Autowired
  43. private WxAuthorizerInfoService authorizerInfoService;
  44. @Autowired
  45. private WxWeappAuditStatusService weappAuditStatusService;
  46. @Autowired
  47. private WxAppinfoService appinfoService;
  48. @Autowired
  49. private MailService mailService;
  50. @Autowired
  51. private String fmAuditEmails;
  52. @PostMapping(value = "/notify")
  53. @ApiOperation("接收ticket回调")
  54. @ResponseBody
  55. public String receiveTicket(@RequestBody Map<String, String> params) throws IOException {
  56. logger.info("[" + getIpAddr() + "]接收微信回调 /ttOpen/notify");
  57. String nonce = params.get("Nonce");
  58. String timestamp = params.get("TimeStamp");
  59. // String signature = params.get("signature");
  60. String encrypt = params.get("Encrypt");
  61. String msgSignature = params.get("MsgSignature");
  62. if (!openService.getTtOpenComponentService().checkSignature(timestamp, nonce, encrypt, msgSignature)) {
  63. throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
  64. }
  65. // aes加密的消息, 解密
  66. TtOpenNotifyMsg openTicket = openService.getTtOpenComponentService().decrypt(encrypt);
  67. // 处理
  68. handleTicket(openTicket);
  69. return "success";
  70. }
  71. /**
  72. * 处理ticket消息
  73. * @param
  74. * @return
  75. */
  76. private void handleTicket(TtOpenNotifyMsg ticket) {
  77. try {
  78. String out = openService.getTtOpenComponentService().route(ticket);
  79. this.logger.info("组装回复信息:{}", out);
  80. } catch (WxErrorException e) {
  81. this.logger.error("notify", e);
  82. }
  83. if (StringUtils.isNotBlank(ticket.getMsgType()) && StringUtils.equalsIgnoreCase(ticket.getMsgType(), "Ticket")) {
  84. logger.info("------------推送ticket通知");
  85. // 保存component_verify_ticket
  86. componentVerifyTicketService.saveOrUpdate(new WxComponentVerifyTicket() {
  87. {
  88. setComponentVerifyTicket(ticket.getTicket());
  89. setCreateTime(DateUtils.stringToDate(ticket.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
  90. setComponentAppid(ticket.getComponentAppId());
  91. setDeadline(new Date(Long.valueOf(System.currentTimeMillis() + (60 * 60 * 1000))));
  92. }
  93. });
  94. }else if(StringUtils.isNotBlank(ticket.getEvent()) && StringUtils.equalsIgnoreCase(ticket.getEvent(), "AUTHORIZED")){
  95. logger.info("------------授权成功通知");
  96. }else if(StringUtils.isNotBlank(ticket.getEvent()) && StringUtils.equalsIgnoreCase(ticket.getEvent(), "UNAUTHORIZED")){
  97. logger.info("------------解除授权成功通知");
  98. }else if(StringUtils.isNotBlank(ticket.getEvent()) && StringUtils.equalsIgnoreCase(ticket.getEvent(), "UPDATE_AUTHORIZED")){
  99. logger.info("------------找回授权码通知");
  100. }else if(StringUtils.isNotBlank(ticket.getEvent()) && StringUtils.equalsIgnoreCase(ticket.getEvent(), "PACKAGE_AUDIT")){
  101. logger.info("------------审核结果通知");
  102. handleWeappAuditedMessage(ticket);
  103. }else{
  104. logger.info("------------未知通知");
  105. }
  106. }
  107. /**
  108. * 处理小程序审核消息
  109. * @param
  110. * @return
  111. */
  112. private boolean handleWeappAuditedMessage(TtOpenNotifyMsg notifyMsg) {
  113. WxWeappAuditStatus auditStatus = weappAuditStatusService.getByAppId(notifyMsg.getAppId());
  114. if(auditStatus == null){
  115. logger.error("------------审核结果通知未找到审核小程序 "+notifyMsg.getAppId());
  116. }
  117. JsonArray auditResults = notifyMsg.getAuditResults();
  118. int status = 0;
  119. String reason = "";
  120. for (int i = 0;i < auditResults.size(); i++) {
  121. JsonObject obj = auditResults.get(i).getAsJsonObject();
  122. if(("douyin").equals(GsonHelper.getString(obj,"hostName"))){
  123. status = GsonHelper.getInteger(obj,"status");
  124. reason = obj.get("reason").toString();
  125. break;
  126. }
  127. }
  128. if (status == 1) {//通过
  129. auditStatus.setAuditStatus(EnumWeappAuditStatus.SUCCESS.getCode());
  130. auditStatus.setAuditErrCode("");
  131. } else {
  132. auditStatus.setAuditStatus(EnumWeappAuditStatus.FAIL.getCode());
  133. auditStatus.setAuditErrCode(reason);
  134. }
  135. auditStatus.setAuditTime(DateUtils.stringToDate(notifyMsg.getEventTime(),"yyyy-MM-dd HH:mm:ss"));
  136. weappAuditStatusService.updateStatus(auditStatus);
  137. // 发邮件
  138. WxAppinfo appinfo = appinfoService.getByAppId(notifyMsg.getAppId());
  139. if (appinfo != null) {
  140. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
  141. StringBuilder titleSB = new StringBuilder();
  142. if (appinfo.getType().equals(EnumAppType.C.getCode())) {
  143. titleSB.append("C端小程序");
  144. } else if (appinfo.getType().equals(EnumAppType.B.getCode())) {
  145. titleSB.append("B端小程序");
  146. } else if (appinfo.getType().equals(EnumAppType.MP_S.getCode())) {
  147. titleSB.append("公众号-服务号");
  148. } else if (appinfo.getType().equals(EnumAppType.MP_P.getCode())) {
  149. titleSB.append("公众号-订阅号");
  150. }
  151. titleSB.append(appinfo.getName());
  152. if (status == 1) {
  153. titleSB.append("审核通过");
  154. } else {
  155. titleSB.append("审核未通过");
  156. }
  157. StringBuilder sb = new StringBuilder();
  158. sb.append(df.format(new Date())).append("\n");
  159. if (status == 1) {
  160. sb.append("审核通过\n");
  161. } else {
  162. sb.append("审核未通过\n").append("原因").append(reason);
  163. }
  164. String[] receivers = fmAuditEmails.split(",");
  165. //发送邮件
  166. mailService.sendSimpleMail(receivers, titleSB.toString(), sb.toString());
  167. }
  168. return false;
  169. }
  170. @PostMapping(value = "/{appId}/callback")
  171. @ApiOperation("消息回调")
  172. public void callback(@PathVariable("appId") String appId, @RequestBody Map<String, String> params) throws IOException {
  173. logger.info("[" + getIpAddr() + "]接收微信APP回调 /{appId}/callback");
  174. String nonce = params.get("Nonce");
  175. String timestamp = params.get("TimeStamp");
  176. // String signature = params.get("signature");
  177. String encrypt = params.get("Encrypt");
  178. String msgSignature = params.get("MsgSignature");
  179. if (!openService.getTtOpenComponentService().checkSignature(timestamp, nonce, encrypt, msgSignature)) {
  180. throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
  181. }
  182. // aes加密的消息, 解密
  183. TtOpenNotifyMsg openTicket = openService.getTtOpenComponentService().decrypt(encrypt);
  184. handleTicket(openTicket);
  185. }
  186. // private void wechatWriteSuccess(PrintWriter printWriter) {
  187. // printWriter.print("success");
  188. // printWriter.flush();
  189. // printWriter.close();
  190. // }
  191. // /**
  192. // * 测试账号特殊处理
  193. // * @param appId
  194. // * @param response
  195. // * @param inMessage
  196. // * @throws IOException
  197. // */
  198. // private void handleWechatTest(@PathVariable("appId") String appId, HttpServletResponse response, WxMpXmlMessage inMessage) throws IOException {
  199. // String out;
  200. // try {
  201. // if (StringUtils.equals(inMessage.getMsgType(), "text")) {
  202. // if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) {
  203. // out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(
  204. // WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback")
  205. // .fromUser(inMessage.getToUser())
  206. // .toUser(inMessage.getFromUser())
  207. // .build(),
  208. // openService.getWxOpenConfigStorage()
  209. // );
  210. // } else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) {
  211. // String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
  212. // WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build();
  213. // openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
  214. // }
  215. // } else if (StringUtils.equals(inMessage.getMsgType(), "event")) {
  216. // WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(inMessage.getEvent() + "from_callback").toUser(inMessage.getFromUser()).build();
  217. // openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
  218. // }
  219. // } catch (WxErrorException e) {
  220. // logger.error("callback", e);
  221. // }
  222. // }
  223. //
  224. // private String getRequestXML(HttpServletRequest request) throws IOException {
  225. // InputStream inStream = request.getInputStream();
  226. // ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
  227. // byte[] buffer = new byte[1024];
  228. // int len = 0;
  229. // while ((len = inStream.read(buffer)) != -1) {
  230. // outSteam.write(buffer, 0, len);
  231. // }
  232. // String resultxml = new String(outSteam.toByteArray(), Charset.forName("UTF-8"));
  233. // logger.info(resultxml);
  234. //
  235. // outSteam.close();
  236. // inStream.close();
  237. // return resultxml;
  238. // }
  239. //
  240. // private void getThreadCount( int i) {
  241. // ThreadGroup group = Thread.currentThread().getThreadGroup();
  242. // ThreadGroup topGroup = group;
  243. // // 遍历线程组树,获取根线程组
  244. // while (group != null) {
  245. // topGroup = group;
  246. // group = group.getParent();
  247. // }
  248. // // 激活的线程数加倍
  249. // int activeCount = topGroup.activeCount();
  250. // // copy into a list that is the exact size
  251. // logger.info("Thread list size == " + i + " : " + activeCount);
  252. //
  253. // }
  254. //
  255. //
  256. // @GetMapping(value = "/createOpenPlatform")
  257. // @ApiOperation("创建微信开放平台")
  258. // public ResultData createOpenPlatform(@RequestParam(value = "appId") String appId) {
  259. // Gson gson = new GsonBuilder().create();
  260. // try {
  261. // WxOpenCreateResult ret = openService.getWxOpenComponentService().createOpenAccount(appId);
  262. // logger.info(ret.toString());
  263. // if (ret.isSuccess()) {
  264. // WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
  265. // if (authorizerInfo != null) {
  266. // authorizerInfo.setId(authorizerInfo.getId());
  267. // authorizerInfo.setOpenAppid(ret.getOpenAppid());
  268. // authorizerInfoService.updateOpenAppid(authorizerInfo);
  269. // }
  270. // }
  271. // return new ResultData(ret.toString());
  272. // } catch (WxErrorException e) {
  273. // logger.error(e.getMessage());
  274. // return new ResultData(Result.ERROR, e.getMessage());
  275. // }
  276. // }
  277. //
  278. // @GetMapping(value = "/bindOpenPlatform")
  279. // @ApiOperation("绑定微信开放平台")
  280. // public ResultData bindOpenPlatform(@RequestParam(value = "appId") String appId, @RequestParam(value = "openAppId") String openAppId) {
  281. // Gson gson = new GsonBuilder().create();
  282. // try {
  283. // Boolean ret = openService.getWxOpenComponentService().bindOpenAccount(appId, openAppId);
  284. // if (ret) {
  285. // WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
  286. // if (authorizerInfo != null) {
  287. // authorizerInfo.setId(authorizerInfo.getId());
  288. // authorizerInfo.setOpenAppid(openAppId);
  289. // authorizerInfoService.updateOpenAppid(authorizerInfo);
  290. // }
  291. // return new ResultData();
  292. // }
  293. // return new ResultData(Result.ERROR, ret.toString());
  294. // } catch (WxErrorException e) {
  295. // logger.error(e.getMessage());
  296. // return new ResultData(Result.ERROR, e.getMessage());
  297. // }
  298. // }
  299. //
  300. // @GetMapping(value = "/unbindOpenPlatform")
  301. // @ApiOperation("解绑微信开放平台")
  302. // public ResultData unbindOpenPlatform(@RequestParam(value = "appId") String appId, @RequestParam(value = "openAppId") String openAppId) {
  303. // Gson gson = new GsonBuilder().create();
  304. // try {
  305. // Boolean ret = openService.getWxOpenComponentService().unbindOpenAccount(appId, openAppId);
  306. // if (ret) {
  307. // WxAuthorizerInfo authorizerInfo = new WxAuthorizerInfo();
  308. // authorizerInfo.setAuthorizerAppid(appId);
  309. // authorizerInfoService.removeOpenAppid(authorizerInfo);
  310. // return new ResultData();
  311. // }
  312. // return new ResultData(Result.ERROR, ret.toString());
  313. // } catch (WxErrorException e) {
  314. // logger.error(e.getMessage());
  315. // return new ResultData(Result.ERROR, e.getMessage());
  316. // }
  317. // }
  318. //
  319. // @GetMapping(value = "/getOpenPlatform")
  320. // @ApiOperation("获取微信开放平台appId")
  321. // public ResultData getOpenPlatform(@RequestParam(value = "appId") String appId) {
  322. // Gson gson = new GsonBuilder().create();
  323. // try {
  324. // WxOpenGetResult ret = openService.getWxOpenComponentService().getOpenAccount(appId);
  325. // logger.info(ret.toString());
  326. // if (ret.isSuccess()) {
  327. // WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
  328. // if (authorizerInfo != null) {
  329. // if(StringUtils.isBlank(authorizerInfo.getOpenAppid()) && StringUtils.isNotBlank(ret.getOpenAppid())) {
  330. // authorizerInfo.setId(authorizerInfo.getId());
  331. // authorizerInfo.setOpenAppid(ret.getOpenAppid());
  332. // authorizerInfoService.updateOpenAppid(authorizerInfo);
  333. // }
  334. // }
  335. // return new ResultData(ret.getOpenAppid());
  336. // }
  337. // return new ResultData(Result.ERROR, ret.toString());
  338. // } catch (WxErrorException e) {
  339. // logger.error(e.getMessage());
  340. // return new ResultData(Result.ERROR, e.getMessage());
  341. // }
  342. // }
  343. //
  344. // @GetMapping(value = "/clearQuota")
  345. // @ApiOperation("代公众号清零quota,每个公众号每个月有10次清零机会,包括在微信公众平台上的清零以及调用API进行清零")
  346. // public ResultData clearQuota(@RequestParam(value = "appId") String appId) {
  347. // try {
  348. // openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).clearQuota(appId);
  349. // return new ResultData();
  350. // } catch (WxErrorException e) {
  351. // logger.error(e.getMessage());
  352. // return new ResultData(Result.ERROR, e.getMessage());
  353. // }
  354. // }
  355. //
  356. // @GetMapping(value = "/getAuthorizerList")
  357. // @ApiOperation("拉取当前所有已授权的帐号基本信息")
  358. // public ResultData getAuthorizerList() {
  359. // try {
  360. // WxOpenAuthorizerListResult authorizerListResult = openService.getWxOpenComponentService().getAuthorizerList(0, 100);
  361. // logger.info("getAuthorizerList: " + authorizerListResult);
  362. // if(authorizerListResult.getTotalCount() > 0) {
  363. // for (Map<String, String> data : authorizerListResult.getList()) {
  364. // String appId = data.get("authorizer_appid");
  365. // String refreshToken = data.get("refresh_token");
  366. // Long authTime = Long.valueOf(data.get("auth_time"));
  367. // Date authDate = new Date(authTime*1000);
  368. //
  369. // if(StringUtils.isBlank(refreshToken)) {
  370. // continue;
  371. // }
  372. //
  373. // WxAuthorizerInfo authorizerInfo = new WxAuthorizerInfo();
  374. // authorizerInfo.setAuthorizerAppid(appId);
  375. // authorizerInfo.setRefreshToken(refreshToken);
  376. // authorizerInfo.setAuthTime(authDate);
  377. // authorizerInfoService.updateAuthAppidInfo(authorizerInfo);
  378. //
  379. // openService.getWxOpenComponentService().getWxOpenConfigStorage().setAuthorizerRefreshToken(appId, refreshToken);
  380. // }
  381. // }
  382. // return new ResultData(authorizerListResult.toString());
  383. // } catch (WxErrorException e) {
  384. // logger.error(e.getMessage());
  385. // return new ResultData(Result.ERROR, e.getMessage());
  386. // }
  387. // }
  388. }