xinelu-api/xinelu-common/src/main/java/com/xinelu/common/utils/AppletChatUtil.java
2023-11-08 17:02:12 +08:00

269 lines
10 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.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
private RedisTemplate<String, Object> redisTemplate;
@Resource
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 二维码地址
*/
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
*/
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;
}
}