package com.jsowell.service; 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.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.agentDev.*; import com.jsowell.pile.service.IPileMerchantInfoService; 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 IPileMerchantInfoService 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 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 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 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 请求结果:{}", JSONObject.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, JSONObject.toJSONString(jsonObject)); logger.info("获取第三方平台 使用授权码获取授权信息 请求参数:{}, 请求结果:{}", JSONObject.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(JSONObject.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); 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, JSONObject.toJSONString(jsonObject)); logger.info("微信第三方平台 通过刷新令牌获取接口令牌 请求参数:{}\n, 请求结果:{}", JSONObject.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", JSONObject.toJSONString(dto.getExtJson())); jsonObject.put("user_version", dto.getUserVersion()); jsonObject.put("user_desc", dto.getUserDesc()); String result = HttpUtils.sendPost(url, JSONObject.toJSONString(jsonObject)); logger.info("获取第三方平台 提交代码 请求参数:{}, 请求结果:{}", JSONObject.toJSONString(jsonObject), result); // 将返回结果转为json对象 JSONObject resultJson = JSONObject.parseObject(result); return resultJson.getString("errmsg"); } /** * 获取类目列表 * * @param authorizerAppid 用户appid * @return */ public List 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 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 itemList = dto.getAuditItems(); String url = "https://api.weixin.qq.com/wxa/submit_audit?access_token=" + authAccessToken; // List --> JsonArray JSONArray itemArray = JSONArray.parseArray(JSONObject.toJSONString(itemList)); // 发送请求 JSONObject jsonObject = new JSONObject(); jsonObject.put("item_list", itemArray); String result = HttpUtils.sendPost(url, JSONObject.toJSONString(jsonObject)); logger.info("微信第三方平台 提交代码审核 请求参数:{}, 请求结果:{}", JSONObject.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, JSONObject.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, JSONObject.toJSONString(jsonObject)); logger.info("微信第三方平台 获取预授权码请求 params:{}, result:{}", JSONObject.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, JSONObject.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 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 settingList = dto.getSettingList(); // 转为 jsonArray JSONArray itemArray = JSONArray.parseArray(JSONObject.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, JSONObject.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.getFirstLevelMerchantIdByAppId(appId); logger.info("微信一键登录 获取merchantId:{}", firstLevelMerchantId); // 下面方法有判断 merchantId 是否为空,因此可直接传值 return memberService.memberRegisterAndLogin(phoneNumber, firstLevelMerchantId, openId); } /** * 根据 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, JSONObject.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"); } }