| @@ -1,16 +1,14 @@ | |||
| package com.iformall.service.toutiao.api; | |||
| import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; | |||
| import com.google.gson.JsonObject; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenAuthorizationInfo; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenTicket; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenNotifyMsg; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||
| import me.chanjar.weixin.open.api.WxOpenConfigStorage; | |||
| import me.chanjar.weixin.open.bean.WxOpenCreateResult; | |||
| import me.chanjar.weixin.open.bean.WxOpenGetResult; | |||
| import me.chanjar.weixin.open.bean.WxOpenMaCodeTemplate; | |||
| import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage; | |||
| import me.chanjar.weixin.open.bean.result.*; | |||
| import java.util.List; | |||
| @@ -86,7 +84,7 @@ public interface TtOpenComponentService { | |||
| boolean checkSignature(String timestamp, String nonce, String encrypt, String signature); | |||
| TtOpenTicket decrypt(String encrypt); | |||
| TtOpenNotifyMsg decrypt(String encrypt); | |||
| String getComponentAccessToken(boolean forceRefresh) throws WxErrorException; | |||
| @@ -104,7 +102,7 @@ public interface TtOpenComponentService { | |||
| String getPreAuthUrl(String redirectUri) throws WxErrorException; | |||
| String route(TtOpenTicket openTicket) throws WxErrorException; | |||
| String route(TtOpenNotifyMsg openTicket) throws WxErrorException; | |||
| /** | |||
| * 使用授权码换取公众号或小程序的接口调用凭据和授权信息. | |||
| @@ -11,7 +11,7 @@ public class TtOpenGsonBuilder { | |||
| static { | |||
| INSTANCE.disableHtmlEscaping(); | |||
| INSTANCE.registerTypeAdapter(TtOpenTicket.class, new TtOpenTicketGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(TtOpenNotifyMsg.class, new TtOpenNotifyMsgGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(TtOpenAuthorizationInfo.class, new TtOpenAuthorizationInfoGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(TtOpenRetrieveCode.class, new TtOpenRetrieveCodeGsonAdapter()); | |||
| @@ -0,0 +1,56 @@ | |||
| package com.iformall.service.toutiao.api.bean; | |||
| import lombok.*; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @author S | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| @NoArgsConstructor | |||
| @AllArgsConstructor | |||
| @Builder | |||
| public class TtOpenNotifyMsg implements Serializable { | |||
| private static final long serialVersionUID = -44544979421396117L; | |||
| private String componentAppId; | |||
| /** | |||
| * Ticket-----推送ticket | |||
| * | |||
| */ | |||
| private String msgType; | |||
| /** | |||
| * PUSH ----- 目前推送ticket | |||
| * AUTHORIZED ------ 授权通知 | |||
| * UNAUTHORIZED ----- 解除授权通知 | |||
| * UPDATE_AUTHORIZED ------- 找回授权码通知 | |||
| */ | |||
| private String event; | |||
| //------推送ticket | |||
| private String ticket; | |||
| private String fromUserName; | |||
| //2019-01-14 12:45:10 | |||
| private String createTime; | |||
| //-----授权/解除授权通知/找回授权码 | |||
| private String appId;//授权小程序的appid | |||
| private String tpAppId;//第三方应用appid | |||
| private String eventTime;//授权/解除授权时间 2019-01-14 12:45:10 | |||
| private String authorizationCode;//授权码 | |||
| private Integer authorizationCodeExpiresIn;//授权码有效期 | |||
| public static TtOpenNotifyMsg fromJson(String json) { | |||
| return TtOpenGsonBuilder.create().fromJson(json, TtOpenNotifyMsg.class); | |||
| } | |||
| } | |||
| @@ -0,0 +1,36 @@ | |||
| package com.iformall.service.toutiao.api.bean; | |||
| import com.google.gson.*; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| import java.lang.reflect.Type; | |||
| /** | |||
| * . | |||
| * | |||
| * @author S | |||
| */ | |||
| public class TtOpenNotifyMsgGsonAdapter implements JsonDeserializer<TtOpenNotifyMsg> { | |||
| @Override | |||
| public TtOpenNotifyMsg deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||
| return convertFromJson(json.getAsJsonObject()); | |||
| } | |||
| protected TtOpenNotifyMsg convertFromJson(JsonObject json) { | |||
| TtOpenNotifyMsg openTicket = new TtOpenNotifyMsg(); | |||
| openTicket.setTicket(GsonHelper.getString(json,"Ticket")); | |||
| openTicket.setFromUserName(GsonHelper.getString(json,"FromUserName")); | |||
| openTicket.setCreateTime(GsonHelper.getString(json,"CreateTime")); | |||
| openTicket.setMsgType(GsonHelper.getString(json,"MsgType")); | |||
| openTicket.setEvent(GsonHelper.getString(json,"Event")); | |||
| openTicket.setAppId(GsonHelper.getString(json,"AppId")); | |||
| openTicket.setTpAppId(GsonHelper.getString(json,"TpAppId")); | |||
| openTicket.setEventTime(GsonHelper.getString(json,"EventTime")); | |||
| openTicket.setAuthorizationCode(GsonHelper.getString(json,"AuthorizationCode")); | |||
| openTicket.setAuthorizationCodeExpiresIn(GsonHelper.getInteger(json,"AuthorizationCodeExpiresIn")); | |||
| return openTicket; | |||
| } | |||
| } | |||
| @@ -1,40 +0,0 @@ | |||
| package com.iformall.service.toutiao.api.bean; | |||
| import com.iformall.service.toutiao.miniapp.bean.TtMaGsonBuilder; | |||
| import lombok.*; | |||
| import java.io.Serializable; | |||
| /** | |||
| * @author S | |||
| */ | |||
| @Getter | |||
| @Setter | |||
| @NoArgsConstructor | |||
| @AllArgsConstructor | |||
| @Builder | |||
| public class TtOpenTicket implements Serializable { | |||
| private static final long serialVersionUID = -44544979421396117L; | |||
| private String accessToken; | |||
| private String ticket; | |||
| private String fromUserName; | |||
| //2019-01-14 12:45:10 | |||
| private String createTime; | |||
| private String msgType; | |||
| private String event; | |||
| private String componentAppId; | |||
| public static TtOpenTicket fromJson(String json) { | |||
| return TtOpenGsonBuilder.create().fromJson(json, TtOpenTicket.class); | |||
| } | |||
| } | |||
| @@ -1,34 +0,0 @@ | |||
| package com.iformall.service.toutiao.api.bean; | |||
| import com.google.gson.*; | |||
| import com.iformall.service.toutiao.miniapp.bean.TtMaSubscribeMessage; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| import java.lang.reflect.Type; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.List; | |||
| /** | |||
| * . | |||
| * | |||
| * @author S | |||
| */ | |||
| public class TtOpenTicketGsonAdapter implements JsonDeserializer<TtOpenTicket> { | |||
| @Override | |||
| public TtOpenTicket deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||
| return convertFromJson(json.getAsJsonObject()); | |||
| } | |||
| protected TtOpenTicket convertFromJson(JsonObject json) { | |||
| TtOpenTicket openTicket = new TtOpenTicket(); | |||
| openTicket.setTicket(GsonHelper.getString(json,"Ticket")); | |||
| openTicket.setFromUserName(GsonHelper.getString(json,"FromUserName")); | |||
| openTicket.setCreateTime(GsonHelper.getString(json,"CreateTime")); | |||
| openTicket.setMsgType(GsonHelper.getString(json,"MsgType")); | |||
| openTicket.setEvent(GsonHelper.getString(json,"Event")); | |||
| return openTicket; | |||
| } | |||
| } | |||
| @@ -10,21 +10,16 @@ import com.iformall.service.toutiao.api.TtOpenService; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenAuthorizationInfo; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenGsonBuilder; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenRetrieveCode; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenTicket; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenNotifyMsg; | |||
| import com.iformall.service.toutiao.utils.MsgDecrypt; | |||
| import com.iformall.service.toutiao.utils.ServerVerification; | |||
| import me.chanjar.weixin.common.error.WxError; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import me.chanjar.weixin.common.util.crypto.SHA1; | |||
| import me.chanjar.weixin.common.util.http.URIUtil; | |||
| import me.chanjar.weixin.common.util.json.WxGsonBuilder; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; | |||
| import me.chanjar.weixin.open.api.WxOpenConfigStorage; | |||
| import me.chanjar.weixin.open.bean.*; | |||
| import me.chanjar.weixin.open.bean.auth.WxOpenAuthorizationInfo; | |||
| import me.chanjar.weixin.open.bean.message.WxOpenXmlMessage; | |||
| import me.chanjar.weixin.open.bean.result.*; | |||
| import me.chanjar.weixin.open.util.WxOpenCryptUtil; | |||
| import me.chanjar.weixin.open.util.json.WxOpenGsonBuilder; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| @@ -97,12 +92,12 @@ public class TtOpenComponentServiceImpl implements TtOpenComponentService { | |||
| } | |||
| @Override | |||
| public TtOpenTicket decrypt(String encrypt) { | |||
| public TtOpenNotifyMsg decrypt(String encrypt) { | |||
| try { | |||
| MsgDecrypt msgDecrypt = new MsgDecrypt(getWxOpenConfigStorage().getComponentAesKey()); | |||
| String plainText = msgDecrypt.decrypt(encrypt); | |||
| log.info("解密信息----------------------------------------"+ plainText); | |||
| TtOpenTicket openTicket = TtOpenTicket.fromJson(plainText); | |||
| TtOpenNotifyMsg openTicket = TtOpenNotifyMsg.fromJson(plainText); | |||
| openTicket.setComponentAppId(getWxOpenConfigStorage().getComponentAppId()); | |||
| return openTicket; | |||
| } catch (Exception e) { | |||
| @@ -212,12 +207,12 @@ public class TtOpenComponentServiceImpl implements TtOpenComponentService { | |||
| @Override | |||
| public String route(final TtOpenTicket ticket) throws WxErrorException { | |||
| public String route(final TtOpenNotifyMsg ticket) throws WxErrorException { | |||
| if (ticket == null) { | |||
| throw new NullPointerException("message is empty"); | |||
| } | |||
| log.info("ticket.getMsgType()"+ticket.getMsgType()); | |||
| if (StringUtils.equalsIgnoreCase(ticket.getMsgType(), "Ticket")) { | |||
| if (StringUtils.isNotBlank(ticket.getMsgType()) && StringUtils.equalsIgnoreCase(ticket.getMsgType(), "Ticket")) { | |||
| getWxOpenConfigStorage().setComponentVerifyTicket(ticket.getTicket()); | |||
| return "success"; | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| package com.iformall.controller; | |||
| import com.iformall.common.Result; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.domain.po.WxAuthorizerInfo; | |||
| import com.iformall.domain.vo.WxWeappInfo; | |||
| @@ -11,6 +12,7 @@ import com.iformall.service.toutiao.api.bean.TtOpenAuthorizationInfo; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| @@ -69,7 +71,7 @@ public class TtAuthController { | |||
| @ApiOperation(value = "授权", notes = "") | |||
| @GetMapping("/jump") | |||
| @ResponseBody | |||
| public void jump(@RequestParam("auth_code") String authorizationCode) { | |||
| public void jump(@RequestParam("authorization_code") String authorizationCode, @RequestParam("expires_in") Integer expiresIn) { | |||
| try { | |||
| TtOpenAuthorizationInfo queryAuthResult = openService.getTtOpenComponentService().getQueryAuth(authorizationCode); | |||
| logger.info("getQueryAuth", queryAuthResult); | |||
| @@ -96,36 +98,51 @@ public class TtAuthController { | |||
| @ApiOperation(value = "刷新", notes = "") | |||
| @GetMapping("/retrieve") | |||
| @ResponseBody | |||
| public ResultData retrieve() { | |||
| WxWeappInfo weappInfo = new WxWeappInfo(); | |||
| weappInfo.setPlat(EnumAppPlat.TOUTIAO.getCode()); | |||
| List<WxWeappInfo> list = authorizerInfoService.getList(weappInfo); | |||
| if(list != null && list.size() > 0){ | |||
| for (WxWeappInfo info: list) { | |||
| try { | |||
| String code = openService.getTtOpenComponentService().retrieveCode(info.getAuthorizerAppid()); | |||
| TtOpenAuthorizationInfo queryAuthResult = openService.getTtOpenComponentService().getQueryAuth(code); | |||
| logger.info("getQueryAuth", queryAuthResult); | |||
| // save auth info | |||
| authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo(){ | |||
| { | |||
| setAuthorizerAppid(queryAuthResult.getAuthorizerAppid()); | |||
| setRefreshToken(queryAuthResult.getAuthorizerRefreshToken()); | |||
| setAccessToken(queryAuthResult.getAuthorizerAccessToken()); | |||
| setAccessTokenExpire(new Date(Long.valueOf(System.currentTimeMillis() + queryAuthResult.getExpiresIn()*1000))); | |||
| setAuthorizationStatus(EnumWxAuthorizationStatus.AUTHORIZED.getCode()); | |||
| setAuthTime(new Date()); | |||
| } | |||
| }); | |||
| } catch (WxErrorException e) { | |||
| logger.error(info.getAuthorizerAppid()+"找回授权码", e); | |||
| throw new RuntimeException(e); | |||
| public ResultData retrieve(@RequestParam("appId") String appId) { | |||
| if(StringUtils.isNotBlank(appId)){ | |||
| try { | |||
| retrieveAuthorizerInfo(appId); | |||
| }catch(Exception e){ | |||
| return new ResultData(Result.ERROR, e.getMessage()); | |||
| } | |||
| }else{ | |||
| WxWeappInfo weappInfo = new WxWeappInfo(); | |||
| weappInfo.setPlat(EnumAppPlat.TOUTIAO.getCode()); | |||
| List<WxWeappInfo> list = authorizerInfoService.getList(weappInfo); | |||
| if(list != null && list.size() > 0){ | |||
| for (WxWeappInfo info: list) { | |||
| try { | |||
| retrieveAuthorizerInfo(info.getAuthorizerAppid()); | |||
| }catch(Exception e){ | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return new ResultData(); | |||
| } | |||
| private void retrieveAuthorizerInfo(String appid){ | |||
| try { | |||
| String code = openService.getTtOpenComponentService().retrieveCode(appid); | |||
| TtOpenAuthorizationInfo queryAuthResult = openService.getTtOpenComponentService().getQueryAuth(code); | |||
| logger.info("getQueryAuth", queryAuthResult); | |||
| // save auth info | |||
| authorizerInfoService.saveOrUpdate(new WxAuthorizerInfo(){ | |||
| { | |||
| setAuthorizerAppid(queryAuthResult.getAuthorizerAppid()); | |||
| setRefreshToken(queryAuthResult.getAuthorizerRefreshToken()); | |||
| setAccessToken(queryAuthResult.getAuthorizerAccessToken()); | |||
| setAccessTokenExpire(new Date(Long.valueOf(System.currentTimeMillis() + queryAuthResult.getExpiresIn()*1000))); | |||
| setAuthorizationStatus(EnumWxAuthorizationStatus.AUTHORIZED.getCode()); | |||
| setAuthTime(new Date()); | |||
| } | |||
| }); | |||
| } catch (WxErrorException e) { | |||
| logger.error(appid+"找回授权码error", e); | |||
| throw new RuntimeException(e); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,30 +1,15 @@ | |||
| package com.iformall.controller; | |||
| 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.WxAuthorizerInfo; | |||
| import com.iformall.domain.po.WxComponentVerifyTicket; | |||
| import com.iformall.enums.EnumWxAuthorizationStatus; | |||
| import com.iformall.service.WxAuthorizerInfoService; | |||
| import com.iformall.service.WxComponentVerifyTicketService; | |||
| import com.iformall.service.toutiao.FmTtOpenService; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenTicket; | |||
| import com.iformall.service.toutiao.api.bean.TtOpenNotifyMsg; | |||
| import com.iformall.utils.DateUtils; | |||
| 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.WxOpenAuthorizerInfoResult; | |||
| import me.chanjar.weixin.open.bean.result.WxOpenAuthorizerListResult; | |||
| import me.chanjar.weixin.open.bean.result.WxOpenQueryAuthResult; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| @@ -34,11 +19,8 @@ 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; | |||
| @@ -73,7 +55,7 @@ public class TtCalllbackController extends BaseController { | |||
| throw new IllegalArgumentException("非法请求,可能属于伪造的请求!"); | |||
| } | |||
| // aes加密的消息, 解密 | |||
| TtOpenTicket openTicket = openService.getTtOpenComponentService().decrypt(encrypt); | |||
| TtOpenNotifyMsg openTicket = openService.getTtOpenComponentService().decrypt(encrypt); | |||
| // 处理 | |||
| handleTicket(openTicket); | |||
| return "success"; | |||
| @@ -84,14 +66,15 @@ public class TtCalllbackController extends BaseController { | |||
| * @param | |||
| * @return | |||
| */ | |||
| private void handleTicket(TtOpenTicket ticket) { | |||
| private void handleTicket(TtOpenNotifyMsg ticket) { | |||
| try { | |||
| String out = openService.getTtOpenComponentService().route(ticket); | |||
| this.logger.info("组装回复信息:{}", out); | |||
| } catch (WxErrorException e) { | |||
| this.logger.error("notify", e); | |||
| } | |||
| if (StringUtils.equalsIgnoreCase(ticket.getMsgType(), "Ticket")) { | |||
| if (StringUtils.isNotBlank(ticket.getMsgType()) && StringUtils.equalsIgnoreCase(ticket.getMsgType(), "Ticket")) { | |||
| logger.info("------------推送ticket通知"); | |||
| // 保存component_verify_ticket | |||
| componentVerifyTicketService.saveOrUpdate(new WxComponentVerifyTicket() { | |||
| { | |||
| @@ -101,6 +84,17 @@ public class TtCalllbackController extends BaseController { | |||
| setDeadline(new Date(Long.valueOf(System.currentTimeMillis() + (60 * 60 * 1000)))); | |||
| } | |||
| }); | |||
| }else if(StringUtils.isNotBlank(ticket.getEvent()) && StringUtils.equalsIgnoreCase(ticket.getEvent(), "AUTHORIZED")){ | |||
| logger.info("------------授权成功通知"); | |||
| }else if(StringUtils.isNotBlank(ticket.getEvent()) && StringUtils.equalsIgnoreCase(ticket.getEvent(), "UNAUTHORIZED")){ | |||
| logger.info("------------解除授权成功通知"); | |||
| }else if(StringUtils.isNotBlank(ticket.getEvent()) && StringUtils.equalsIgnoreCase(ticket.getEvent(), "UPDATE_AUTHORIZED")){ | |||
| logger.info("------------找回授权码通知"); | |||
| }else{ | |||
| logger.info("------------未知通知"); | |||
| } | |||
| } | |||