xinelu-api/xinelu-common/src/main/java/com/xinelu/common/utils/AppletChatUtil.java

269 lines
10 KiB
Java
Raw Normal View History

package com.xinelu.common.utils;
import com.alibaba.fastjson2.JSON;
import com.xinelu.common.config.AppletChatConfig;
import com.xinelu.common.config.XinELuConfig;
import com.xinelu.common.constant.Constants;
import com.xinelu.common.entity.AppletAccessToken;
import com.xinelu.common.entity.AppletLoginVO;
import com.xinelu.common.entity.AppletPhoneVO;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* @Description 微信小程序工具类
* @Author 纪寒
* @Date 2022-08-17 16:11:10
* @Version 1.0
*/
@Slf4j
@Component
public class AppletChatUtil {
@Resource
2023-11-08 17:02:12 +08:00
private RedisTemplate<String, Object> redisTemplate;
@Resource
2023-11-08 17:02:12 +08:00
private AppletChatConfig appletChatConfig;
/**
* 返回成功状态码
*/
private static final int SUCCESS_CODE = 0;
/**
* 小程序登录url
*/
private static final String APPLET_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
/**
* 小程序accessToken的url
*/
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
/**
* 小程序获取用户手机号的url
*/
private static final String PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";
/**
* 获取小程序二维码接口地址
*/
private static final String GET_APPLET_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
/**
* JSON数据格式标识
*/
private static final String JSON_DATA_FORMAT = "Content-Type: application/json; encoding=utf-8";
/**
* 生成小程序二维码图片失败标识
*/
private static final String FAIL = "FAIL";
/**
* 根据登录编码获取微信用户信息
*
* @param appletId 小程序id
* @param secret 小程序秘钥
* @param code 登录凭证码
* @param grantType 授权类型
* @return 登录信息
*/
public static AppletLoginVO getAppletLoginInfo(String appletId, String secret, String code, String grantType) {
//请求地址
String appletLoginUrl = APPLET_LOGIN_URL
+ "?appid=" + appletId
+ "&secret=" + secret
+ "&js_code=" + code
+ "&grant_type=" + grantType;
//发送请求
String result = HttpUtils.sendGet(appletLoginUrl);
if (StringUtils.isBlank(result)) {
throw new ServiceException("获取微信小程序用户信息失败", 201);
}
return JSON.parseObject(result, AppletLoginVO.class);
}
/**
* 获取微信小程序的accessToken
*
* @param appletId 小程序id
* @param secret 小程序秘钥
* @return accessToken信息
*/
public static AppletAccessToken getAppletAccessToken(String appletId, String secret) {
//请求路径
String accessTokenUrl = ACCESS_TOKEN_URL + "&appid=" + appletId + "&secret=" + secret;
//发送请求
String result = HttpUtils.sendGet(accessTokenUrl);
if (StringUtils.isBlank(result)) {
throw new ServiceException("获取微信小程序accessToken信息失败", 201);
}
return JSON.parseObject(result, AppletAccessToken.class);
}
/**
* 获取微信小程序的手机号码
*
* @param code 登录凭证
* @param accessToken 小程序accessToken
* @return 手机信息
*/
public static AppletPhoneVO getAppletPhoneInfo(String code, String accessToken) {
//请求地址
String phoneUrl = PHONE_NUMBER_URL + accessToken;
//请求参数
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("code", code);
String param = JSON.toJSONString(paramMap);
//发送POST请求
String result = HttpUtils.sendPostJson(phoneUrl, param);
if (StringUtils.isBlank(result)) {
throw new ServiceException("获取微信小程序手机号失败", 201);
}
return JSON.parseObject(result, AppletPhoneVO.class);
}
/**
* 递归获取小程序二维码信息
*
* @param weChatCodeId 输入id
* @param failFlag 调用失败标识
* @param fileName 文件名称
* @param appletPageUrl 二维码跳转路径
* @param filePathWeChatCodeUrl 文件保存路径
* @return java.lang.String 二维码地址
*/
2023-11-08 17:02:12 +08:00
public String createAppletCode(Long weChatCodeId, boolean failFlag, String fileName, String appletPageUrl, String filePathWeChatCodeUrl) {
if (BooleanUtils.isTrue(failFlag)) {
//删除原有Redis中的key值
String accessTokenKey = Constants.NURSE_STATION_APPLET_ACCESS_TOKEN + "accessToken";
Object object = redisTemplate.opsForValue().get(accessTokenKey);
if (Objects.nonNull(object)) {
redisTemplate.delete(accessTokenKey);
}
}
//删除原有Redis中缓存的AccessToken
String appletAccessToken = getAppletAccessToken();
if (StringUtils.isBlank(appletAccessToken)) {
throw new ServiceException("获取小程序凭证信息失败,请联系管理员!");
}
Map<String, Object> params = new HashMap<>();
params.put("scene", weChatCodeId);
params.put("page", appletPageUrl);
String body = JSON.toJSONString(params);
String filePath = XinELuConfig.getProfile() + filePathWeChatCodeUrl + "/" + weChatCodeId;
//调用微信接口获取小程序二维码并将其上传到服务器中
return getAppletCodePicture(appletAccessToken, body, filePath, fileName);
}
/**
* 根据小程序AccessToken获取小程序的二维码图片
*
* @param accessToken 微信小程序的accessToken
* @param body 接口传输参数
* @param filePath 文件路径
* @param fileName 文件名称
* @return 小程序的二维码图片
*/
public static String getAppletCodePicture(String accessToken, String body, String filePath, String fileName) {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost(GET_APPLET_CODE_URL + accessToken);
try {
StringEntity entity = new StringEntity(body, "UTF-8");
entity.setContentType("image/png");
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
String contentType = response.getEntity().getContentType().toString();
if (StringUtils.equals(contentType, JSON_DATA_FORMAT)) {
return FAIL;
}
String absolutePath = getAbsoluteFile(filePath, fileName).getAbsolutePath();
try (InputStream inputStream = response.getEntity().getContent(); FileOutputStream out = new FileOutputStream(absolutePath)) {
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.flush();
}
return absolutePath;
} catch (Exception e) {
log.error("获取小程序二维码接口调用失败,失败原因为:{}", e.getMessage());
return null;
}
}
/**
* 创建文件路径
*
* @param uploadDir 路径名称
* @param fileName 文件名称
* @return File 文件目录
*/
public static File getAbsoluteFile(String uploadDir, String fileName) {
File file = new File(uploadDir + File.separator + fileName);
if (!file.exists()) {
if (!file.getParentFile().exists()) {
boolean mkdirs = file.getParentFile().mkdirs();
if (BooleanUtils.isFalse(mkdirs)) {
throw new ServiceException("文件路径创建失败,请联系管理员!");
}
}
}
return file;
}
/**
* 获取小程序AccessToken方法
*
* @return 小程序的AccessToken
*/
2023-11-08 17:02:12 +08:00
public String getAppletAccessToken() {
String accessToken;
String accessTokenKey = Constants.NURSE_STATION_APPLET_ACCESS_TOKEN + "accessToken";
//从Redis中取出accessToken
Object object = redisTemplate.opsForValue().get(accessTokenKey);
if (Objects.isNull(object)) {
//没有获取accessToken
AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
if (Objects.isNull(appletAccessToken)) {
throw new ServiceException("获取微信小程序accessToken信息失败");
}
if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != SUCCESS_CODE) {
throw new ServiceException("获取微信小程序accessToken信息失败失败信息为" + appletAccessToken.getErrmsg(), 201);
}
if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
throw new ServiceException("accessToken信息为空");
}
//存入Redis中
redisTemplate.opsForValue().set(accessTokenKey, appletAccessToken.getAccessToken(), 3600, TimeUnit.SECONDS);
accessToken = appletAccessToken.getAccessToken();
} else {
accessToken = (String) object;
}
return accessToken;
}
}