269 lines
10 KiB
Java
269 lines
10 KiB
Java
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;
|
||
}
|
||
}
|