package com.project.common.utils; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.project.common.exception.base.BaseException; import com.project.common.utils.http.HttpUtils; import com.project.common.vo.UserWxPhoneInfoVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.TimeUnit; import static com.project.common.constant.WechatConstants.*; @Component @Slf4j public class WeChatUtils implements CommandLineRunner { @Override public void run(String... args) throws Exception { getAccessToken(); } private static StringRedisTemplate stringRedisTemplate; @Autowired public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) { WeChatUtils.stringRedisTemplate = stringRedisTemplate; } private static String appid; private static String secret; @Value("${pay.wx.xcx.appid}") public void setAppid(String appid) { this.appid = appid; } @Value("${pay.wx.xcx.secret}") public void setSecret(String secret) { this.secret = secret; } /** * 刷新access_token */ public static void refreshAccessToken() { String url = WEIXIN_ACCESS_TOKEN_URL + "?grant_type=client_credential&appid=" + appid + "&secret=" + secret; try { //向微信发送请求 String result = HttpUtils.sendGet(url, null); //将获取的结果转化为JSONObject JSONObject re = JSON.parseObject(result); String accessToken = re.getString("access_token"); //设置access_token的生命周期为1小时 int expires_in = 3600; if (StringUtils.isNotBlank(accessToken)) { stringRedisTemplate .opsForValue() .set(appid + ":access_token", accessToken, expires_in, TimeUnit.SECONDS); } } catch (Exception e) { log.error("getAccess_token ERROR, appid = " + appid, e); } } /** * 获取微信公众号access_token * @return */ public static String getAccessToken() { String accessToken = stringRedisTemplate.opsForValue().get(appid + ":access_token"); if (StringUtils.isBlank(accessToken)) { String url = WEIXIN_ACCESS_TOKEN_URL + "?grant_type=client_credential&appid=" + appid + "&secret=" + secret; try { //向微信发送请求 String result = HttpUtils.sendGet(url, null); //将获取的结果转化为JSONObject JSONObject re = JSON.parseObject(result); accessToken = re.getString("access_token"); //设置access_token的生命周期为1小时 int expires_in = 3600; if (StringUtils.isNotBlank(re.getString("expires_in"))) { expires_in = re.getIntValue("expires_in"); } if (StringUtils.isNotBlank(accessToken)) { stringRedisTemplate .opsForValue() .set(appid + ":access_token", accessToken, expires_in, TimeUnit.SECONDS); } } catch (Exception e) { log.error("getAccess_token ERROR, appid = " + appid, e); } } return accessToken; } /** * 获取微信用户信息 * * @param accessToken 用户的access_token * @param openid 用户的openid * @return 包含用户信息的Map * @throws Exception */ public static Map getUserInfo(String accessToken, String openid) throws Exception { String url = USER_INFO_URL + "?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN"; String result = HttpUtils.sendGet(url, null); JSONObject jsonObject = JSON.parseObject(result); System.out.println(jsonObject.toString()); String unionid = jsonObject.getString("unionid"); String nickname = jsonObject.getString("nickname"); String avatar = jsonObject.getString("headimgurl"); String phoneNumber = jsonObject.getString("phoneNumber"); // 获取用户手机号需要用户在小程序内进行授权 Map map = new HashMap<>(); map.put("unionId", unionid); map.put("nickname", nickname); map.put("avatar", avatar); map.put("phoneNumber", phoneNumber); return map; } /** * 获取用户手机号 * @return */ public static String getUserPhone(String accessToken, String code) { String phone = ""; String urlPath = WEIXIN_GET_USERPHONENUMBER_URL + accessToken; try { Map headerMap = new HashMap<>(); headerMap.put("content-type", "application/json"); Map dataMap = new HashMap<>(); dataMap.put("code", code); String result = HttpUtils.callPostServices(urlPath, dataMap, headerMap); JSONObject re = JSON.parseObject(result); if (re.getString("errmsg").equals("ok")) { String resultStr = re.getString("phone_info"); UserWxPhoneInfoVO phoneInfoVO = JSONObject.parseObject(resultStr, UserWxPhoneInfoVO.class); if (phoneInfoVO != null) { phone = phoneInfoVO.getPhoneNumber(); } } else { log.error("getUserPhone ERROR " + re.getString("errmsg")); stringRedisTemplate.delete(appid + ":access_token"); } } catch (Exception e) { log.error("getUserPhone ERROR, accessToken = " + accessToken, e); } return phone; } /** * 获取用户小程序openID * @param code * @return */ public static String getOpenId(String code) { //通过小程序端的code获取openid StringBuilder urlPath = new StringBuilder(WEIXIN_JSCODE2SESSION_URL); urlPath.append(String.format("?appid=%s", appid)); urlPath.append(String.format("&secret=%s", secret)); urlPath.append(String.format("&js_code=%s", code)); urlPath.append(String.format("&grant_type=%s", "authorization_code")); //向微信发送请求 String result = HttpUtils.sendGet(urlPath.toString(), null); //将获取的结果转化为JSONObject JSONObject object = JSON.parseObject(result); if(object != null && StringUtils.isNotBlank(object.getString("openid"))){ result = object.getString("openid"); }else{ throw new BaseException("获取用户openid失败!"); } return result; } /** * 小程序授权获取openID和unionID * * @return */ public static Map oauth2GetUnion(String code) { //通过小程序端的code获取openid StringBuilder urlPath = new StringBuilder(WEIXIN_JSCODE2SESSION_URL); urlPath.append(String.format("?appid=%s", appid)); urlPath.append(String.format("&secret=%s", secret)); urlPath.append(String.format("&js_code=%s", code)); urlPath.append(String.format("&grant_type=%s", "authorization_code")); //向微信发送请求 String resultStr = HttpUtils.sendGet(urlPath.toString(), null); Map result = new HashMap<>(); //将获取的结果转化为JSONObject JSONObject object = JSON.parseObject(resultStr); if(object != null && StringUtils.isNotBlank(object.getString("openid"))){ result.put("wxOpenid", object.getString("openid")); result.put("unionId", object.getString("unionid")); result.put("sessionKey", object.getString("session_key")); }else{ throw new BaseException("获取用户openid失败!"); } return result; } }