|
@@ -1,12 +1,28 @@
|
|
|
package com.idiot.operationbackend.service.impl;
|
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.google.common.cache.*;
|
|
|
+import com.idiot.operationbackend.config.PlatformProperties;
|
|
|
import com.idiot.operationbackend.service.facade.WeChatService;
|
|
|
import com.idiot.operationbackend.support.Constants;
|
|
|
+import com.idiot.operationbackend.support.wechat.AesException;
|
|
|
+import com.idiot.operationbackend.support.wechat.WXBizMsgCrypt;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.InitializingBean;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.http.*;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.util.LinkedMultiValueMap;
|
|
|
+import org.springframework.util.MultiValueMap;
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* @author wang xiao
|
|
@@ -15,19 +31,126 @@ import java.util.Objects;
|
|
|
@Service
|
|
|
public class WeChatServiceImpl implements WeChatService, InitializingBean {
|
|
|
|
|
|
- @Override
|
|
|
- public String authCallBack(Map<String, String> param) {
|
|
|
|
|
|
+ private final Logger logger = LoggerFactory.getLogger(WeChatServiceImpl.class);
|
|
|
+
|
|
|
+ private final Cache<String,String> cache = CacheBuilder.newBuilder()
|
|
|
+ .concurrencyLevel(8)
|
|
|
+ .expireAfterWrite(100, TimeUnit.MINUTES)
|
|
|
+ .initialCapacity(10)
|
|
|
+ .maximumSize(100)
|
|
|
+ .recordStats()
|
|
|
+ .removalListener(notification -> logger.warn("cache {} was removed, cause is {}" ,notification.getKey(), notification.getCause()))
|
|
|
+ .build();
|
|
|
+
|
|
|
+ private WXBizMsgCrypt pc;
|
|
|
+
|
|
|
+ @Resource(name = "rpcRestTemplate")
|
|
|
+ private RestTemplate restTemplate;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private PlatformProperties properties;
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String notice(Map<String, String> param) {
|
|
|
if (Objects.isNull(param)) {
|
|
|
return Constants.SUCCESS;
|
|
|
}
|
|
|
- String appId = param.get("AppId");
|
|
|
String infoType = param.get("InfoType");
|
|
|
- return null;
|
|
|
+ String appId = param.get("AppId");
|
|
|
+ String ticket = param.get("ComponentVerifyTicket");
|
|
|
+ logger.info("接受微信验证票据数据,infoType:{},appId:{},ticket:{}",infoType,appId,ticket);
|
|
|
+ cache.put(String.format("component_verify_ticket_%s",appId),ticket);
|
|
|
+ return Constants.SUCCESS;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
@Override
|
|
|
- public void afterPropertiesSet() throws Exception {
|
|
|
+ public String decryptMsg(String msgSignature, String timestamp, String nonce, String data) {
|
|
|
+ try {
|
|
|
+ return pc.decryptMsg(msgSignature,timestamp,nonce,data);
|
|
|
+ }catch (AesException e){
|
|
|
+ logger.error("微信解密数据发生错误----->msgSignature:{},timestamp:{},nonce:{},data:{}",msgSignature,
|
|
|
+ timestamp,nonce,data);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
+ @Override
|
|
|
+ public String encryptMsg(String data) {
|
|
|
+ String timestamp = Long.toString(System.currentTimeMillis());
|
|
|
+ String nonce = pc.getRandomStr();
|
|
|
+ try {
|
|
|
+ return pc.encryptMsg(data,timestamp,nonce);
|
|
|
+ }catch (AesException e){
|
|
|
+ logger.error("微信加密数据发生错误----->timestamp:{},nonce:{},data:{}",timestamp,nonce,data);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getComponentAccessToken() {
|
|
|
+ String appId = properties.getAppId();
|
|
|
+ String componentAccessToken = cache.getIfPresent(String.format("component_access_token_%s",appId));
|
|
|
+ if ( !StringUtils.isEmpty(componentAccessToken)) {
|
|
|
+ return componentAccessToken;
|
|
|
+ }
|
|
|
+ String requestUrl = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ MultiValueMap<String,String> params = new LinkedMultiValueMap<>(3);
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+ String ticket = cache.getIfPresent(String.format("component_verify_ticket_%s",appId));
|
|
|
+ params.add("component_appid",appId);
|
|
|
+ params.add("component_appsecret",properties.getAppSecret());
|
|
|
+ params.add("component_verify_ticket",ticket);
|
|
|
+ HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
|
|
|
+ ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, String.class);
|
|
|
+ String jsonStr = response.getBody();
|
|
|
+ logger.info("请求微信获取令牌component_access_token 请求appId:{},ticket:{},微信返回结果:{}",appId,ticket,jsonStr);
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(jsonStr);
|
|
|
+ componentAccessToken = jsonObject.getString("component_access_token");
|
|
|
+ cache.put(String.format("component_access_token_%s",appId),componentAccessToken);
|
|
|
+ return componentAccessToken;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getPreAuthCode() {
|
|
|
+ String appId = properties.getAppId();
|
|
|
+ String requestUrl = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=COMPONENT_ACCESS_TOKEN";
|
|
|
+ String componentAccessToken = getComponentAccessToken();
|
|
|
+ requestUrl = requestUrl.replace("COMPONENT_ACCESS_TOKEN",componentAccessToken);
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ MultiValueMap<String,String> params = new LinkedMultiValueMap<>(1);
|
|
|
+ params.add("component_appid",appId);
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+ HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
|
|
|
+ ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, String.class);
|
|
|
+ String jsonStr = response.getBody();
|
|
|
+ logger.info("请求微信获取预授权码 请求appId:{},微信返回结果:{}",appId,jsonStr);
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(jsonStr);
|
|
|
+ return jsonObject.getString("pre_auth_code");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getPreAuthUrl() {
|
|
|
+ String preAuthUrl = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=APPID&pre_auth_code=PREAUTHCODE&redirect_uri=URI&auth_type=1";
|
|
|
+ String appId = properties.getAppId();
|
|
|
+ String preAuthCode = getPreAuthCode();
|
|
|
+ preAuthUrl = preAuthUrl.replace("APPID",appId).replace("PREAUTHCODE",preAuthCode);
|
|
|
+ logger.info("生成预授权地址, preAuthUrl is {}",preAuthUrl);
|
|
|
+ return preAuthUrl;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterPropertiesSet() throws Exception {
|
|
|
+ logger.info("WeChatService类--------------->正在初始化");
|
|
|
+ pc = new WXBizMsgCrypt(properties.getToken(), properties.getSecret(), properties.getAppId());
|
|
|
+ logger.info("cache size is {}",cache.size());
|
|
|
+ logger.info("WeChatService类--------------->初始化完成");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|