Files
jsowell-charger-web/jsowell-admin/src/main/java/com/jsowell/service/AgentDevService.java
2024-06-14 17:15:36 +08:00

695 lines
30 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.jsowell.service;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.AgentDev.AuditStatusEnum;
import com.jsowell.common.util.DictUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.http.HttpUtils;
import com.jsowell.common.util.wxplatform.AesException;
import com.jsowell.common.util.wxplatform.WXBizMsgCrypt;
import com.jsowell.common.util.wxplatform.WXXmlToMapUtil;
import com.jsowell.pile.domain.agentDev.AuditItem;
import com.jsowell.pile.domain.agentDev.CategoryInfo;
import com.jsowell.pile.domain.agentDev.UserInfoSetting;
import com.jsowell.pile.dto.MemberRegisterAndLoginDTO;
import com.jsowell.pile.dto.agentDev.*;
import com.jsowell.pile.service.PileMerchantInfoService;
import com.jsowell.pile.vo.agentDev.AuthInfoVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* 代开发小程序Service
*
* @author Lemon
* @Date 2023/7/27 15:58
*/
@Service
public class AgentDevService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private MemberService memberService;
@Autowired
private RedisCache redisCache;
@Autowired
private PileMerchantInfoService pileMerchantInfoService;
/**
* 第三方平台 appid
*/
private static final String PLATFORM_APP_ID = "wxac3b282a58b9a4a8";
/**
* 第三方平台 secret
*/
private static final String PLATFORM_APP_SECRET = "eb8adc2689b4f27be7ae75a4b646dbe6";
/**
* 第三方平台 消息加解密Key
*/
private static final String PLATFORM_AES_KEY = "9TDTYLBLYGG1IOU9VOLXHNIKKJ65NU40S0ITJ0BFQOU";
/**
* 第三方平台 消息校验Token
*/
private static final String PLATFORM_COMPONENT_TOKEN = "XD83ZUJWTVRB4OSN";
/**
* 解析请求
*
* @param timeStamp
* @param nonce
* @param msgSignature
* @param postData
* @return
*/
public String parseRequest(String timeStamp, String nonce, String msgSignature, String postData) {
logger.info("==============================开始授权事件接收URL=================================");
try {
//这个类是微信官网提供的解密类,需要用到消息校验Token 消息加密Key和服务平台appid
WXBizMsgCrypt pc = new WXBizMsgCrypt(PLATFORM_COMPONENT_TOKEN, PLATFORM_AES_KEY, PLATFORM_APP_ID);
String xml = pc.decryptMsg(msgSignature, timeStamp, nonce, postData);
Map<String, String> result = WXXmlToMapUtil.xmlToMap(xml);// 将xml转为map
logger.info("微信第三方平台推送消息解析后 result:{}", result);
// 获取 infoType 确认是哪个事件
String infoType = MapUtils.getString(result, "InfoType");
if (StringUtils.equals("component_verify_ticket", infoType)) {
// 授权票据事件
verifyTicket(result);
} else if (StringUtils.equals("authorized", infoType)
|| StringUtils.equals("updateauthorized", infoType)
|| StringUtils.equals("unauthorized", infoType)) {
// 授权成功通知 authorized、授权更新通知 updateauthorized、 取消授权通知 unauthorized
// 小程序/公众号授权事件
authorizedInform(result);
}
} catch (AesException e) {
e.printStackTrace();
}
logger.info("==============================结束授权事件接收URL=================================");
return "success";
}
/**
* 验证票据事件
*
* @param map 微信第三方平台推送消息解析后的 map
* @return
*/
private String verifyTicket(Map<String, String> map) {
// 获取验证票据
String componentVerifyTicket = MapUtils.getString(map, "ComponentVerifyTicket");
if (StringUtils.isEmpty(componentVerifyTicket)) {
throw new RuntimeException("微信开放平台,第三方平台获取【验证票据】为空");
}
String redisKey = CacheConstants.COMPONENT_VERIFY_TICKET + PLATFORM_APP_ID;
// 查缓存,看是否已经过期
// String verifyTicket = redisCache.getCacheObject(redisKey);
// if (verifyTicket != null) {
// // 先删除旧缓存
// redisCache.deleteObject(redisKey);
// }
// 存入Redis 过期时间: 官方12小时但十分钟推送一次, 因此可设置 20 分钟过期
redisCache.setCacheObject(redisKey, componentVerifyTicket, 20, TimeUnit.MINUTES);
String newVerifyTicket = redisCache.getCacheObject(redisKey);
// 存储平台授权票据,保存ticket
// redisTemplate.opsForValue().set("component_verify_ticket", componentVerifyTicket, 60 * 12, TimeUnit.SECONDS);
// String verifyTicket = redisTemplate.opsForValue().get("component_verify_ticket").toString();
logger.info("====================授权票据【ComponentVerifyTicket】" + newVerifyTicket + "】====================");
return newVerifyTicket;
}
/**
* 小程序/公众号授权事件
* https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/2.0/api/Before_Develop/authorize_event.html
*
* @param map
*/
private void authorizedInform(Map<String, String> map) {
// 获取通知类型
String infoType = MapUtils.getString(map, "InfoType");
// 小程序appid
String authorizerAppid = MapUtils.getString(map, "AuthorizerAppid");
if (StringUtils.equals("unauthorized", infoType)) {
logger.info("微信开放平台,第三方平台,用户:{} 取消授权", authorizerAppid);
return;
}
logger.info("微信开放平台,第三方平台小程序/公众号授权事件 params:{}", map);
// 用户授权码 redisKey
String authCodeRedisKey = CacheConstants.COMPONENT_AUTHORIZATION_CODE + authorizerAppid;
// 查缓存
String authorizationCode = redisCache.getCacheObject(authCodeRedisKey);
// 如果此用户之前有缓存,需把原来的删除
if (StringUtils.isNotBlank(authorizationCode)) {
redisCache.deleteObject(authCodeRedisKey);
}
// 获取授权码
authorizationCode = MapUtils.getString(map, "AuthorizationCode");
logger.info("微信开放平台,第三方平台小程序/公众号授权事件 用户授权码:{}", authorizationCode);
if (StringUtils.isBlank(authorizationCode)
|| StringUtils.isBlank(authorizerAppid)) {
throw new RuntimeException("微信开放平台,第三方平台获取【授权码】为空");
}
redisCache.setCacheObject(authCodeRedisKey, authorizationCode, 1, TimeUnit.HOURS);
logger.info("微信开放平台,第三方平台小程序/公众号授权事件 success, authorizationCode:{}", authorizationCode);
}
/**
* 获取第三方平台 token
*
* @param dto
* @return
*/
public String getComponentToken(GetComponentTokenDTO dto) {
String verifyTicket = dto.getVerifyTicket();
String redisKey = CacheConstants.COMPONENT_ACCESS_TOKEN + dto.getAppId();
// 先判断缓存中是否有 token
String token = redisCache.getCacheObject(redisKey);
if (StringUtils.isNotBlank(token)) {
// 不为空直接返回
return token;
}
// 为空再去请求获取新令牌
String url = "https://api.weixin.qq.com/cgi-bin/component/api_component_token";
if (StringUtils.isBlank(verifyTicket)) {
// 获取缓存中的票据
verifyTicket = redisCache.getCacheObject(CacheConstants.COMPONENT_VERIFY_TICKET + dto.getAppId());
logger.info("获取第三方平台缓存中票据:{}", verifyTicket);
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("component_appid", dto.getAppId());
jsonObject.put("component_appsecret", dto.getAppSecret());
jsonObject.put("component_verify_ticket", verifyTicket);
String result = HttpUtils.sendPost(url, jsonObject.toString());
JSONObject jsonResult = JSONObject.parseObject(result);
logger.info("获取第三方平台 token 请求结果:{}", JSON.toJSONString(jsonResult));
// 获取返回值中的 token
token = jsonResult.getString("component_access_token");
if (token == null) {
throw new RuntimeException("获取第三方平台 token 异常!");
}
logger.info("获取第三方平台 token component_access_token:{}", token);
// 存入redis, 有效期 1小时50分, 官方 2 小时
redisCache.setCacheObject(redisKey, token, 110, TimeUnit.MINUTES);
return token;
}
/**
* 使用授权码获取授权信息
* 并将授权信息中的 接口调用令牌、刷新令牌存入缓存
*
* @param authorizationCode
*/
public AuthInfoVO getAuthInfoByAuthCode(String authorizationCode) {
// 获取 component_access_token
GetComponentTokenDTO dto = GetComponentTokenDTO.builder()
.appId(PLATFORM_APP_ID)
.appSecret(PLATFORM_APP_SECRET)
.verifyTicket(null)
.build();
String componentToken = getComponentToken(dto);
// 使用授权码获取授权信息 url
String url = "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=" + componentToken;
JSONObject jsonObject = new JSONObject();
jsonObject.put("component_appid", PLATFORM_APP_ID);
jsonObject.put("authorization_code", authorizationCode);
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
logger.info("获取第三方平台 使用授权码获取授权信息 请求参数:{}, 请求结果:{}", JSON.toJSONString(jsonObject), result);
// 将结果转换成json对象
JSONObject resultJson = JSONObject.parseObject(result);
if (Objects.isNull(resultJson)) {
throw new RuntimeException("获取第三方平台 使用授权码获取授权信息 请求结果 为空");
}
// AuthInfoVO authInfoVO = (AuthInfoVO) resultJson.get("authorization_info");
AuthInfoVO authInfoVO = JSONObject.parseObject(JSON.toJSONString(resultJson.get("authorization_info")), AuthInfoVO.class);
if (authInfoVO == null) {
throw new RuntimeException("获取第三方平台 使用授权码获取授权信息 error");
}
logger.info("获取第三方平台 使用授权码获取授权信息 authInfoVO:{}", authInfoVO);
String authorizerAccessToken = authInfoVO.getAuthorizerAccessToken(); // 接口调用令牌, 默认有效期 7200 秒
String authorizerRefreshToken = authInfoVO.getAuthorizerRefreshToken(); // 刷新令牌 永久保存
String authorizerAppid = authInfoVO.getAuthorizerAppid(); // 授权方 appid
String authAccessTokenKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + authorizerAppid;
redisCache.setCacheObject(authAccessTokenKey, authorizerAccessToken, 120, TimeUnit.MINUTES);
String authRefreshTokenKey = CacheConstants.AUTHORIZER_REFRESH_TOKEN + authorizerAppid;
redisCache.setCacheObject(authRefreshTokenKey, authorizerRefreshToken);
return authInfoVO;
}
/**
* 获取用户接口令牌
* @param authAppId
* @return
*/
private String getAuthAccessToken(String authAppId) {
// 先查缓存是否有值
String redisKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + authAppId;
String authAccessToken = redisCache.getCacheObject(redisKey);
if (StringUtils.isNotBlank(authAccessToken)) {
return authAccessToken;
}
// 如果没有,就通过刷新令牌去重新获取
String refreshTokenKey = CacheConstants.AUTHORIZER_REFRESH_TOKEN + authAppId;
String refreshToken = redisCache.getCacheObject(refreshTokenKey);
if (StringUtils.isBlank(refreshToken)) {
refreshToken = DictUtils.getDictValue("authorizer_refresh_token", authAppId);
}
return getAuthTokenByRefreshToken(authAppId, refreshToken);
}
/**
* 通过刷新令牌获取接口令牌
* @param authAppId
* @param refreshToken
* @return
*/
private String getAuthTokenByRefreshToken(String authAppId, String refreshToken) {
GetComponentTokenDTO dto = GetComponentTokenDTO.builder()
.appId(PLATFORM_APP_ID)
.appSecret(PLATFORM_APP_SECRET)
.build();
String componentToken = getComponentToken(dto);
String url = "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=" + componentToken;
// 拼接参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("component_appid", PLATFORM_APP_ID);
jsonObject.put("authorizer_appid", authAppId);
jsonObject.put("authorizer_refresh_token", refreshToken);
// 发送请求
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
logger.info("微信第三方平台 通过刷新令牌获取接口令牌 请求参数:{}, 请求结果:{}", JSON.toJSONString(jsonObject), result);
// 将返回结果转成 json 对象
JSONObject resultJson = JSONObject.parseObject(result);
String authAccessToken = resultJson.getString("authorizer_access_token"); // 用户接口令牌
int expiresTime = resultJson.getInteger("expires_in"); // 接口令牌过期时间
String authorizerRefreshToken = resultJson.getString("authorizer_refresh_token"); // 用户刷新令牌
// 先将刷新令牌删除
String refreshTokenKey = CacheConstants.AUTHORIZER_REFRESH_TOKEN + authAppId;
redisCache.deleteObject(refreshTokenKey);
// 分别存入缓存
String authTokenKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + authAppId;
redisCache.setCacheObject(authTokenKey, authAccessToken, 2, TimeUnit.HOURS);
redisCache.setCacheObject(refreshTokenKey, authorizerRefreshToken);
return redisCache.getCacheObject(authTokenKey);
}
/**
* 提交代码并生成体验版小程序
*
* @param dto
* @return
*/
public String commitCode(CommitCodeDTO dto) {
// String redisKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + dto.getAuthorizerAppid();
// String authAccessToken = redisCache.getCacheObject(redisKey);
// if (StringUtils.isBlank(authAccessToken)) {
// throw new RuntimeException("微信第三方平台 提交代码 error: authAccessToken为空");
// }
String authAccessToken = getAuthAccessToken(dto.getAuthorizerAppid());
// 提交代码 url
String url = "https://api.weixin.qq.com/wxa/commit?access_token=" + authAccessToken;
JSONObject jsonObject = new JSONObject();
jsonObject.put("template_id", dto.getTemplateId());
jsonObject.put("ext_json", JSON.toJSONString(dto.getExtJson()));
jsonObject.put("user_version", dto.getUserVersion());
jsonObject.put("user_desc", dto.getUserDesc());
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
logger.info("获取第三方平台 提交代码 请求参数:{}, 请求结果:{}", JSON.toJSONString(jsonObject), result);
// 将返回结果转为json对象
JSONObject resultJson = JSONObject.parseObject(result);
return resultJson.getString("errmsg");
}
/**
* 获取类目列表
*
* @param authorizerAppid 用户appid
* @return
*/
public List<CategoryInfo> getAllCategoryName(String authorizerAppid) {
// String redisKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + authorizerAppid;
// String authAccessToken = redisCache.getCacheObject(redisKey);
// if (StringUtils.isBlank(authAccessToken)) {
// throw new RuntimeException("微信第三方平台 获取类目名称信息 error: authAccessToken为空");
// }
String authAccessToken = getAuthAccessToken(authorizerAppid);
String url = "https://api.weixin.qq.com/wxa/get_category?access_token=" + authAccessToken;
String result = HttpUtils.sendGet(url);
logger.info("获取第三方平台 获取类目名称信息 请求结果:{}", result);
// 将返回结果转为json对象
JSONObject resultJson = JSONObject.parseObject(result);
int errCode = (int) resultJson.get("errcode");
if (errCode != 0) {
// 不为 0 则说明有错误
logger.error("获取第三方平台 获取类目名称信息 error:{}", resultJson.getString("errmsg"));
return new ArrayList<>();
}
// 将 jsonArray 转成 List
JSONArray categoryList = resultJson.getJSONArray("category_list");
List<CategoryInfo> categoryInfos = categoryList.toList(CategoryInfo.class);
if (CollectionUtils.isEmpty(categoryInfos)) {
logger.info("获取第三方平台 获取类目名称信息 error");
return new ArrayList<>();
}
return categoryInfos;
}
/**
* 提交代码审核
* https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/code-management/submitAudit.html
*
* @param dto
* @return
*/
public String submitAudit(SubmitAuditDTO dto) {
// String redisKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + dto.getAuthorizerAppid();
// String authAccessToken = redisCache.getCacheObject(redisKey);
// if (StringUtils.isBlank(authAccessToken)) {
// throw new RuntimeException("微信第三方平台 提交代码审核 error: authAccessToken为空");
// }
String authAccessToken = getAuthAccessToken(dto.getAuthorizerAppid());
List<AuditItem> itemList = dto.getAuditItems();
String url = "https://api.weixin.qq.com/wxa/submit_audit?access_token=" + authAccessToken;
// List --> JsonArray
JSONArray itemArray = JSONArray.parseArray(JSON.toJSONString(itemList));
// 发送请求
JSONObject jsonObject = new JSONObject();
jsonObject.put("item_list", itemArray);
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
logger.info("微信第三方平台 提交代码审核 请求参数:{}, 请求结果:{}", JSON.toJSONString(jsonObject), result);
// 将返回结果转为json对象
JSONObject resultJson = JSONObject.parseObject(result);
int errCode = (int) resultJson.get("errcode");
if (errCode != 0) {
String errMsg = resultJson.getString("errmsg");
logger.info("微信第三方平台 提交代码审核 error, {}", errMsg);
return errMsg;
}
// 获取审核编码并返回
int auditId = resultJson.getInteger("auditid");
return String.valueOf(auditId);
}
/**
* 获取审核状态
* @param dto
* @return
*/
public String getAuditStatus(GetAuditStatusDTO dto) {
if (StringUtils.isBlank(dto.getAuditId())) {
throw new RuntimeException("微信第三方平台 查询审核单状态 error:审核id为空");
}
// 获取用户接口调用令牌
String authAccessToken = getAuthAccessToken(dto.getAuthorizerAppid());
// String redisKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + dto.getAuthorizerAppid();
// String authAccessToken = redisCache.getCacheObject(redisKey);
// if (StringUtils.isBlank(authAccessToken)) {
// throw new RuntimeException("微信第三方平台 查询审核单状态 error: authAccessToken为空");
// }
String url = "https://api.weixin.qq.com/wxa/get_auditstatus?access_token=" + authAccessToken;
// 拼接参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("auditid", dto.getAuditId());
// 发送请求
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
// 将返回结果转为json对象
JSONObject resultJson = JSONObject.parseObject(result);
int errCode = (int) resultJson.get("errcode");
if (errCode != Constants.zero) {
String errMsg = resultJson.getString("errmsg");
logger.info("微信第三方平台 提交代码审核 error, {}", errMsg);
return errMsg;
}
int status = (int) resultJson.get("status");
if (status == Constants.one || status == Constants.four) {
// 当 status = 1 时,返回的拒绝原因; status = 4 时,返回的延后原因
return resultJson.getString("reason");
}
return AuditStatusEnum.getValueByCode(status);
}
/**
* 获取预授权码
*
* @return
*/
public String getPreAuthorizerCode() {
String redisKey = CacheConstants.PLATFORM_PRE_AUTH_CODE + PLATFORM_APP_ID;
// 先查缓存
String preAuthCode = redisCache.getCacheObject(redisKey);
if (StringUtils.isNotBlank(preAuthCode)) {
return preAuthCode;
}
// 获取平台令牌
GetComponentTokenDTO dto = GetComponentTokenDTO.builder()
.appId(PLATFORM_APP_ID)
.appSecret(PLATFORM_APP_SECRET)
.verifyTicket(null)
.build();
String componentToken = getComponentToken(dto);
// 拼接参数
String url = "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=" + componentToken;
JSONObject jsonObject = new JSONObject();
jsonObject.put("component_appid", PLATFORM_APP_ID);
// 发送请求
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
logger.info("微信第三方平台 获取预授权码请求 params:{}, result:{}", JSON.toJSONString(jsonObject), result);
// 将返回结果转成json对象
JSONObject resultJson = JSONObject.parseObject(result);
preAuthCode = resultJson.getString("pre_auth_code");
if (StringUtils.isBlank(preAuthCode)) {
logger.error("微信第三方平台 获取预授权码为空");
return null;
}
// 存入缓存 有效期 1800 秒
redisCache.setCacheObject(redisKey, preAuthCode, 30, TimeUnit.MINUTES);
return preAuthCode;
}
/**
* 拼接授权链接
*
* @param dto
* @return
*/
public String concatenateAuthLinks(ConcatenateAuthLinkDTO dto) {
String versionType = dto.getVersionType();
String url = "";
String platformAppid = dto.getPlatformAppID() == null ? PLATFORM_APP_ID : dto.getPlatformAppID();
if (StringUtils.equals(Constants.ONE, versionType)) {
// 1-PC版链接
url = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=" + platformAppid
+ "&pre_auth_code=" + dto.getPreAuthCode() + "&redirect_uri=" + dto.getRedirectUri() + "&auth_type=" + dto.getAuthType();
} else {
// 2-H5版链接
url = "https://open.weixin.qq.com/wxaopen/safe/bindcomponent?action=bindcomponent&no_scan=1&component_appid=" + platformAppid
+ "&pre_auth_code=" + dto.getPreAuthCode() + "&redirect_uri=" + dto.getRedirectUri() + "&auth_type=" + dto.getAuthType();
}
return url;
}
/**
* 发布已通过审核的小程序 调用本接口可以发布最后一个审核通过的小程序代码版本
* https://developers.weixin.qq.com/doc/oplatform/openApi/OpenApiDoc/miniprogram-management/code-management/release.html
* @return
*/
public String releaseProcedure(String authorizerAppid){
// 获取用户接口调用令牌
String authAccessToken = getAuthAccessToken(authorizerAppid);
// String redisKey = CacheConstants.AUTHORIZER_ACCESS_TOKEN + authorizerAppid;
// String authAccessToken = redisCache.getCacheObject(redisKey);
// if (StringUtils.isBlank(authAccessToken)) {
// throw new RuntimeException("微信第三方平台 发布已通过审核的小程序 error: authAccessToken为空");
// }
String url = "https://api.weixin.qq.com/wxa/release?access_token=" + authAccessToken;
JSONObject jsonObject = new JSONObject();
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
// 将返回结果转为json对象
JSONObject resultJson = JSONObject.parseObject(result);
// int errCode = (int) resultJson.get("errcode");
return resultJson.getString("errmsg");
}
public static void main(String[] args) {
JSONArray array = new JSONArray();
array.set(0, "1");
array.set(1, "2");
array.set(2, "3");
List<String> list = array.toList(String.class);
System.out.println(list);
}
/**
* 授权回调 处理方法
*/
public void getAuthCallback(String authCode, String expiresIn) {
logger.info("授权回调 处理方法 authCode:{}, expiresIn:{}", authCode, expiresIn);
AuthInfoVO authInfo = getAuthInfoByAuthCode(authCode);
if (authInfo == null) {
return;
}
String authorizerAppid = authInfo.getAuthorizerAppid();
// 先查询 redis 看有没有
String redisKey = CacheConstants.COMPONENT_AUTHORIZATION_CODE + authorizerAppid;
// String redisAuthCode = redisCache.getCacheObject(redisKey);
// if (StringUtils.isNotBlank(redisAuthCode)) {
// // 有,先删除
// redisCache.deleteObject(redisKey);
// }
// 删除预缓存码
String preAuthCodeKey = CacheConstants.PLATFORM_PRE_AUTH_CODE + authorizerAppid;
redisCache.deleteObject(preAuthCodeKey);
// 将 authCode 存入缓存
redisCache.setCacheObject(redisKey, authCode, 1, TimeUnit.HOURS);
}
/**
* 设置小程序用户隐私保护指引
* @param dto
* @return
*/
public String setPrivacySetting(PrivacySettingDTO dto) {
// 获取用户接口调用令牌
String authAccessToken = getAuthAccessToken(dto.getAuthAppId());
String url = "https://api.weixin.qq.com/cgi-bin/component/setprivacysetting?access_token=" + authAccessToken;
List<UserInfoSetting> settingList = dto.getSettingList();
// 转为 jsonArray
JSONArray itemArray = JSONArray.parseArray(JSON.toJSONString(settingList));
// 拼接参数
JSONObject jsonObject = new JSONObject();
jsonObject.put("privacy_ver", dto.getPrivacyVer());
jsonObject.put("setting_list", itemArray);
jsonObject.put("owner_setting", dto.getOwnerSetting());
// 发送请求
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
// 转为 json 对象
JSONObject resultJson = JSONObject.parseObject(result);
return resultJson.getString("errmsg");
}
/**
* 微信一键登录
* @param dto
*/
public String wechatLogin(AgentWechatLoginDTO dto) {
String appId = dto.getAppId();
// 获取用户接口调用令牌
String authAccessToken = getAuthAccessToken(appId);
// 获取手机号
String phoneNumber = getPhoneNumberByCode(dto.getPhoneNumberCode(), authAccessToken);
// 获取openId
String openId = getOpenIdByCode(dto.getOpenIdCode(), appId);
// 通过 appid 查询 merchantId
String firstLevelMerchantId = pileMerchantInfoService.getFirstLevelMerchantIdByWxAppId(appId);
logger.info("微信一键登录 获取merchantId:{}", firstLevelMerchantId);
// 下面方法有判断 merchantId 是否为空,因此可直接传值
MemberRegisterAndLoginDTO loginDTO = MemberRegisterAndLoginDTO.builder()
.openId(openId)
.firstLevelMerchantId(firstLevelMerchantId)
.mobileNumber(phoneNumber)
.requestSource(dto.getRequestSource())
.build();
return memberService.memberRegisterAndLogin(loginDTO); // 其他一级运营商,微信一键登录
}
/**
* 根据 code 获取登录用户手机号
* @param code
* @param authAccessToken
* @return
*/
private String getPhoneNumberByCode(String code, String authAccessToken) {
String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + authAccessToken;
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", code);
String result = HttpUtils.sendPost(url, JSON.toJSONString(jsonObject));
// 将返回值转成 json 对象
JSONObject resultJson = JSONObject.parseObject(result);
Integer errCode = resultJson.getInteger("errcode");
if (errCode == Constants.zero) {
return JSONObject.parseObject(resultJson.getString("phone_info")).getString("phoneNumber");
}
return resultJson.getString("errmsg");
}
/**
* 通过 code 获取 openid
* @param openIdCode
* @param appId
* @return
*/
private String getOpenIdByCode(String openIdCode, String appId) {
GetComponentTokenDTO dto = GetComponentTokenDTO.builder()
.appId(PLATFORM_APP_ID)
.appSecret(PLATFORM_APP_SECRET)
.build();
String componentToken = getComponentToken(dto);
String url = "https://api.weixin.qq.com/sns/component/jscode2session?appid=" + appId
+ "&js_code=" + openIdCode + "&grant_type=authorization_code&component_appid=" + PLATFORM_APP_ID + "&component_access_token=" + componentToken;
String result = HttpUtils.sendGet(url);
JSONObject resultJson = JSONObject.parseObject(result);
return resultJson.getString("openid");
}
}