|
- package com.iformall.controller;
-
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.google.gson.Gson;
- import com.google.gson.GsonBuilder;
- import com.iformall.common.Result;
- import com.iformall.common.ResultData;
- import com.iformall.controller.base.BaseController;
- import com.iformall.domain.po.*;
- import com.iformall.enums.*;
- import com.iformall.service.*;
- import com.iformall.service.wechat.FmOpenService;
- import io.swagger.annotations.Api;
- import io.swagger.annotations.ApiOperation;
- import me.chanjar.weixin.common.error.WxErrorException;
- import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
- import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
- import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
- import me.chanjar.weixin.open.bean.WxOpenCreateResult;
- import me.chanjar.weixin.open.bean.WxOpenGetResult;
- import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage;
- import me.chanjar.weixin.open.bean.result.*;
- import org.apache.commons.lang3.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.*;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.PrintWriter;
- import java.nio.charset.Charset;
- import java.util.Date;
- import java.util.Map;
-
- @Controller
- @RequestMapping("/wxOpen")
- @Api(description = "微信第三方开放平台回调相关接口")
- public class WechatCalllbackController extends BaseController {
- private final Logger logger = LoggerFactory.getLogger(this.getClass());
-
- @Autowired
- protected FmOpenService openService;
-
- @Autowired
- private WxComponentVerifyTicketService componentVerifyTicketService;
-
- @Autowired
- private WxAuthorizerInfoService authorizerInfoService;
-
- @PostMapping(value = "/notify")
- @ApiOperation("接收ticket回调")
- @ResponseBody
- public String receiveTicket(HttpServletRequest request) throws IOException {
- logger.info("[" + getIpAddr() + "]接收微信回调 /wxOpen/notify");
-
- String timestamp = request.getParameter("timestamp");
- String nonce = request.getParameter("nonce");
- String signature = request.getParameter("signature");
- String encType = request.getParameter("encrypt_type");
- String msgSignature = request.getParameter("msg_signature");
-
- if (!StringUtils.equalsIgnoreCase("aes", encType)
- || !openService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
- throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
- }
-
- String resultxml = getRequestXML(request);
-
- logger.info("\n接收微信回调:[signature=[{}], encType=[{}], msgSignature=[{}],"
- + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
- signature, encType, msgSignature, timestamp, nonce, resultxml);
-
- // aes加密的消息, 解密
- WxOpenXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedXml(resultxml,
- openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
- this.logger.info("接收微信回调,消息解密后内容为:{} ", inMessage.toString());
-
- // 处理
- handleTicket(inMessage);
- return "success";
- }
-
- /**
- * 处理ticket消息
- * @param inMessage
- * @return
- */
- private void handleTicket(WxOpenXmlMessage inMessage) {
- try {
- String out = openService.getWxOpenComponentService().route(inMessage);
- this.logger.info("组装回复信息:{}", out);
- } catch (WxErrorException e) {
- this.logger.error("notify", e);
- }
- if (inMessage.getInfoType().equalsIgnoreCase(EnumWxAuthorizationInfoType.COMPONENT_VERIFY_TICKET.getMessage())) {
- // 保存component_verify_ticket
- componentVerifyTicketService.saveOrUpdate(new WxComponentVerifyTicket() {
- {
- setComponentVerifyTicket(inMessage.getComponentVerifyTicket());
- setCreateTime(new Date(Long.valueOf(inMessage.getCreateTime() * 1000)));
- setComponentAppid(inMessage.getAppId());
- setDeadline(new Date(Long.valueOf(System.currentTimeMillis() + (60 * 60 * 1000))));
- }
- });
- } else if (inMessage.getInfoType().equalsIgnoreCase(EnumWxAuthorizationInfoType.AUTHORIZED.getMessage()) ||
- inMessage.getInfoType().equalsIgnoreCase(EnumWxAuthorizationInfoType.UPDATEAUTHORIZED.getMessage())) {
- // 审核通过
- handleWeappAuditedMessage(inMessage);
- } else if (inMessage.getInfoType().equals(EnumWxAuthorizationInfoType.UNAUTHORIZED.getMessage())) {
- // 授权取消
- authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo() {
- {
- setAuthorizerAppid(inMessage.getAuthorizerAppid());
- setAuthorizationStatus(EnumWxAuthorizationStatus.UNAUTHORIZED.getCode());
- setAuthTime(new Date());
- }
- });
- }
- }
-
- /**
- * 处理小程序审核消息
- * @param inMessage
- * @return
- */
- private boolean handleWeappAuditedMessage(WxOpenXmlMessage inMessage) {
- // 审核通过
- try {
- WxOpenQueryAuthResult queryAuthResult = openService.getWxOpenComponentService().getQueryAuth(inMessage.getAuthorizationCode());
- logger.info("getQueryAuth", queryAuthResult);
-
- WxOpenAuthorizerInfoResult openAuthorizerInfoResult = openService.getWxOpenComponentService().getAuthorizerInfo(
- queryAuthResult.getAuthorizationInfo().getAuthorizerAppid());
- logger.info(openAuthorizerInfoResult.toString());
- // save auth info
- authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo() {
- {
- setAuthorizerAppid(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAppid());
- setAlias(openAuthorizerInfoResult.getAuthorizerInfo().getAlias());
- setHeadImg(openAuthorizerInfoResult.getAuthorizerInfo().getHeadImg());
- setQrcodeUrl(openAuthorizerInfoResult.getAuthorizerInfo().getQrcodeUrl());
- setRefreshToken(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerRefreshToken());
- setAccessToken(openAuthorizerInfoResult.getAuthorizationInfo().getAuthorizerAccessToken());
- setAccessTokenExpire(new Date(Long.valueOf(System.currentTimeMillis() + openAuthorizerInfoResult.getAuthorizationInfo().getExpiresIn()*1000)));
- setAuthorizationStatus(EnumWxAuthorizationStatus.AUTHORIZED.getCode());
- setAuthTime(new Date());
- }
- });
- return true;
- } catch (WxErrorException e) {
- logger.error(e.getMessage());
- }
- return false;
- }
-
- @RequestMapping(value = "/{appId}/callback")
- @ApiOperation("消息回调")
- public void callback(@PathVariable("appId") String appId, HttpServletRequest request, HttpServletResponse response) throws IOException {
- logger.info("[" + getIpAddr() + "]接收微信APP回调 /{appId}/callback");
- String timestamp = request.getParameter("timestamp");
- String nonce = request.getParameter("nonce");
- String signature = request.getParameter("signature");
- String encType = request.getParameter("encrypt_type");
- String openid = request.getParameter("openid");
- String msgSignature = request.getParameter("msg_signature");
-
- // 第三方平台一定接收的是加密的消息
- if (!StringUtils.equalsIgnoreCase("aes", encType)
- || !openService.getWxOpenComponentService().checkSignature(timestamp, nonce, signature)) {
- throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
- }
-
- String resultxml = getRequestXML(request);
-
- logger.info("接收微信APP回调:[appId=[{}], openid=[{}], signature=[{}], encType=[{}], msgSignature=[{}],"
- + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ",
- appId, openid, signature, encType, msgSignature, timestamp, nonce, resultxml);
-
-
- String out = "";
- // aes加密的消息, 解密
- WxMpXmlMessage inMessage = WxOpenXmlMessage.fromEncryptedMpXml(resultxml,
- openService.getWxOpenConfigStorage(), timestamp, nonce, msgSignature);
- logger.info("接收微信APP回调,消息解密后内容为:\n{}", inMessage.toString());
-
- // 全网发布测试用例
- if (StringUtils.equalsAnyIgnoreCase(appId, "wx570bc396a51b8ff8", "wxd101a85aa106f53e")) {
- handleWechatTest(appId, response, inMessage);
- PrintWriter printWriter = response.getWriter();
- wechatWriteSuccess(printWriter);
- return;
- }
-
- // 实际 消息 处理
- //handleCallbackMessage(appId, response, inMessage);
- WxMpXmlOutMessage outMessage = openService.getWxOpenMessageRouter().route(inMessage, appId);
- if(outMessage == null) {
- PrintWriter printWriter = response.getWriter();
- wechatWriteSuccess(printWriter);
- }
- PrintWriter printWriter = response.getWriter();
- wechatWriteSuccess(printWriter);
- }
-
- private void wechatWriteSuccess(PrintWriter printWriter) {
- printWriter.print("success");
- printWriter.flush();
- printWriter.close();
- }
-
- /**
- * 测试账号特殊处理
- * @param appId
- * @param response
- * @param inMessage
- * @throws IOException
- */
- private void handleWechatTest(@PathVariable("appId") String appId, HttpServletResponse response, WxMpXmlMessage inMessage) throws IOException {
- String out;
- try {
- if (StringUtils.equals(inMessage.getMsgType(), "text")) {
- if (StringUtils.equals(inMessage.getContent(), "TESTCOMPONENT_MSG_TYPE_TEXT")) {
- out = WxOpenXmlMessage.wxMpOutXmlMessageToEncryptedXml(
- WxMpXmlOutMessage.TEXT().content("TESTCOMPONENT_MSG_TYPE_TEXT_callback")
- .fromUser(inMessage.getToUser())
- .toUser(inMessage.getFromUser())
- .build(),
- openService.getWxOpenConfigStorage()
- );
- } else if (StringUtils.startsWith(inMessage.getContent(), "QUERY_AUTH_CODE:")) {
- String msg = inMessage.getContent().replace("QUERY_AUTH_CODE:", "") + "_from_api";
- WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(msg).toUser(inMessage.getFromUser()).build();
- openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
- }
- } else if (StringUtils.equals(inMessage.getMsgType(), "event")) {
- WxMpKefuMessage kefuMessage = WxMpKefuMessage.TEXT().content(inMessage.getEvent() + "from_callback").toUser(inMessage.getFromUser()).build();
- openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).getKefuService().sendKefuMessage(kefuMessage);
- }
- } catch (WxErrorException e) {
- logger.error("callback", e);
- }
- }
-
- private String getRequestXML(HttpServletRequest request) throws IOException {
- InputStream inStream = request.getInputStream();
- ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int len = 0;
- while ((len = inStream.read(buffer)) != -1) {
- outSteam.write(buffer, 0, len);
- }
- String resultxml = new String(outSteam.toByteArray(), Charset.forName("UTF-8"));
- logger.info(resultxml);
-
- outSteam.close();
- inStream.close();
- return resultxml;
- }
-
- private void getThreadCount( int i) {
- ThreadGroup group = Thread.currentThread().getThreadGroup();
- ThreadGroup topGroup = group;
- // 遍历线程组树,获取根线程组
- while (group != null) {
- topGroup = group;
- group = group.getParent();
- }
- // 激活的线程数加倍
- int activeCount = topGroup.activeCount();
- // copy into a list that is the exact size
- logger.info("Thread list size == " + i + " : " + activeCount);
-
- }
-
-
- @GetMapping(value = "/createOpenPlatform")
- @ApiOperation("创建微信开放平台")
- public ResultData createOpenPlatform(@RequestParam(value = "appId") String appId) {
- Gson gson = new GsonBuilder().create();
- try {
- WxOpenCreateResult ret = openService.getWxOpenComponentService().createOpenAccount(appId);
- logger.info(ret.toString());
- if (ret.isSuccess()) {
- WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
- if (authorizerInfo != null) {
- authorizerInfo.setId(authorizerInfo.getId());
- authorizerInfo.setOpenAppid(ret.getOpenAppid());
- authorizerInfoService.updateOpenAppid(authorizerInfo);
- }
- }
- return new ResultData(ret.toString());
- } catch (WxErrorException e) {
- logger.error(e.getMessage());
- return new ResultData(Result.ERROR, e.getMessage());
- }
- }
-
- @GetMapping(value = "/bindOpenPlatform")
- @ApiOperation("绑定微信开放平台")
- public ResultData bindOpenPlatform(@RequestParam(value = "appId") String appId, @RequestParam(value = "openAppId") String openAppId) {
- Gson gson = new GsonBuilder().create();
- try {
- Boolean ret = openService.getWxOpenComponentService().bindOpenAccount(appId, openAppId);
- if (ret) {
- WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
- if (authorizerInfo != null) {
- authorizerInfo.setId(authorizerInfo.getId());
- authorizerInfo.setOpenAppid(openAppId);
- authorizerInfoService.updateOpenAppid(authorizerInfo);
- }
- return new ResultData();
- }
- return new ResultData(Result.ERROR, ret.toString());
- } catch (WxErrorException e) {
- logger.error(e.getMessage());
- return new ResultData(Result.ERROR, e.getMessage());
- }
- }
-
- @GetMapping(value = "/unbindOpenPlatform")
- @ApiOperation("解绑微信开放平台")
- public ResultData unbindOpenPlatform(@RequestParam(value = "appId") String appId, @RequestParam(value = "openAppId") String openAppId) {
- Gson gson = new GsonBuilder().create();
- try {
- Boolean ret = openService.getWxOpenComponentService().unbindOpenAccount(appId, openAppId);
- if (ret) {
- WxAuthorizerInfo authorizerInfo = new WxAuthorizerInfo();
- authorizerInfo.setAuthorizerAppid(appId);
- authorizerInfoService.removeOpenAppid(authorizerInfo);
- return new ResultData();
- }
- return new ResultData(Result.ERROR, ret.toString());
- } catch (WxErrorException e) {
- logger.error(e.getMessage());
- return new ResultData(Result.ERROR, e.getMessage());
- }
- }
-
- @GetMapping(value = "/getOpenPlatform")
- @ApiOperation("获取微信开放平台appId")
- public ResultData getOpenPlatform(@RequestParam(value = "appId") String appId) {
- Gson gson = new GsonBuilder().create();
- try {
- WxOpenGetResult ret = openService.getWxOpenComponentService().getOpenAccount(appId);
- logger.info(ret.toString());
- if (ret.isSuccess()) {
- WxAuthorizerInfo authorizerInfo = authorizerInfoService.getByAppId(appId);
- if (authorizerInfo != null) {
- if(StringUtils.isBlank(authorizerInfo.getOpenAppid()) && StringUtils.isNotBlank(ret.getOpenAppid())) {
- authorizerInfo.setId(authorizerInfo.getId());
- authorizerInfo.setOpenAppid(ret.getOpenAppid());
- authorizerInfoService.updateOpenAppid(authorizerInfo);
- }
- }
- return new ResultData(ret.getOpenAppid());
- }
- return new ResultData(Result.ERROR, ret.toString());
- } catch (WxErrorException e) {
- logger.error(e.getMessage());
- return new ResultData(Result.ERROR, e.getMessage());
- }
- }
-
- @GetMapping(value = "/clearQuota")
- @ApiOperation("代公众号清零quota,每个公众号每个月有10次清零机会,包括在微信公众平台上的清零以及调用API进行清零")
- public ResultData clearQuota(@RequestParam(value = "appId") String appId) {
- try {
- openService.getWxOpenComponentService().getWxMpServiceByAppid(appId).clearQuota(appId);
- return new ResultData();
- } catch (WxErrorException e) {
- logger.error(e.getMessage());
- return new ResultData(Result.ERROR, e.getMessage());
- }
- }
-
- @GetMapping(value = "/getAuthorizerList")
- @ApiOperation("拉取当前所有已授权的帐号基本信息")
- public ResultData getAuthorizerList() {
- try {
- WxOpenAuthorizerListResult authorizerListResult = openService.getWxOpenComponentService().getAuthorizerList(0, 100);
- logger.info("getAuthorizerList: " + authorizerListResult);
- if(authorizerListResult.getTotalCount() > 0) {
- for (Map<String, String> data : authorizerListResult.getList()) {
- String appId = data.get("authorizer_appid");
- String refreshToken = data.get("refresh_token");
- Long authTime = Long.valueOf(data.get("auth_time"));
- Date authDate = new Date(authTime*1000);
-
- if(StringUtils.isBlank(refreshToken)) {
- continue;
- }
-
- WxAuthorizerInfo authorizerInfo = new WxAuthorizerInfo();
- authorizerInfo.setAuthorizerAppid(appId);
- authorizerInfo.setRefreshToken(refreshToken);
- authorizerInfo.setAuthTime(authDate);
- authorizerInfoService.updateAuthAppidInfo(authorizerInfo);
-
- openService.getWxOpenComponentService().getWxOpenConfigStorage().setAuthorizerRefreshToken(appId, refreshToken);
- }
- }
- return new ResultData(authorizerListResult.toString());
- } catch (WxErrorException e) {
- logger.error(e.getMessage());
- return new ResultData(Result.ERROR, e.getMessage());
- }
- }
- }
|