package com.caimei.components; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.caimei.model.ResponseJson; import com.caimei.util.HttpRequest; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.security.AlgorithmParameters; import java.security.Security; import java.util.HashMap; import java.util.Map; /** * 微信 服务工具类 * * @author : Charles * @date : 2021/3/9 */ @Slf4j @Component public class WeChatService { @Value("${wx.AppId}") private String heHeAppId; @Value("${wx.AppSecret}") private String heHeAppSecret; /*private RedisService redisService; @Autowired public void setRedisService(RedisService redisService) { this.redisService = redisService; }*/ public static class Keys { public static final String OPEN_ID = "openid"; public static final String UNION_ID = "unionid"; public static final String SESSION_KEY = "session_key"; } static { // BouncyCastle是一个开源的加解密解决方案 Security.addProvider(new BouncyCastleProvider()); } /** * AES解密 * * @param data 密文,被加密的数据 * @param key 秘钥 * @param iv 偏移量 * @param encodingFormat 解密后的结果需要进行的编码 * @return 解密结果 */ public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception { // 被加密的数据 byte[] dataByte = Base64.decodeBase64(data); // 加密秘钥 byte[] keyByte = Base64.decodeBase64(key); // 偏移量 byte[] ivByte = Base64.decodeBase64(iv); try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); // 初始化 cipher.init(Cipher.DECRYPT_MODE, spec, parameters); byte[] resultByte = cipher.doFinal(dataByte); if (null != resultByte && resultByte.length > 0) { return new String(resultByte, encodingFormat); } return null; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 小程序微信授权登录,获取openid * * @param code 微信凭证 * @param headers HttpHeaders * @param mode 1:采美小程序,2:收款工具小程序appId * @return HashMap */ public ResponseJson> getInfoMapByApplets(String code, HttpHeaders headers, Integer mode) { log.info("Start get SessionKey"); Map returnMap = new HashMap<>(4); // 获取当前微信小程序的环境 String referer = headers.getFirst("Referer"); log.info("referer-is----:" + referer); returnMap.put("referer", referer); String requestUrl = "https://api.weixin.qq.com/sns/jscode2session"; Map requestUrlParam = new HashMap(4); // 呵呵商城小程序appId requestUrlParam.put("appid", heHeAppId); log.info("呵呵商城appId: ---" + heHeAppId); // 呵呵商城小程序appSecret requestUrlParam.put("secret", heHeAppSecret); // 小程序端返回的code requestUrlParam.put("js_code", code); // 默认参数 requestUrlParam.put("grant_type", "authorization_code"); // 发送post请求读取调用微信接口获取openid用户唯一标识 String infos; try { infos = HttpRequest.sendPost(requestUrl, requestUrlParam); } catch (Exception e) { return ResponseJson.error("服务器内部异常", returnMap); } // 解析相应内容(转换成json对象) JSONObject jsonObject = JSON.parseObject(infos); String openId = jsonObject.getString(Keys.OPEN_ID); String unionId = jsonObject.getString(Keys.UNION_ID); String sessionKey = jsonObject.getString(Keys.SESSION_KEY); String errCode = jsonObject.getString("errcode"); String errMsg = jsonObject.getString("errmsg"); log.info("openId----->" + openId + ", unionId------>" + unionId); returnMap.put(Keys.OPEN_ID, openId); returnMap.put(Keys.UNION_ID, unionId); returnMap.put(Keys.SESSION_KEY, sessionKey); boolean errFlag = StringUtils.isNotEmpty(errCode) && ("-1".equals(errCode) || "40029".equals(errCode) || "45011".equals(errCode)); if (errFlag) { return ResponseJson.error(-1, errMsg, returnMap); } return ResponseJson.success(returnMap); } /** * 网页授权登录,通过code获取openid * * @param code 微信code * @param source 来源 * @return */ public Map getInfoMapByWeb(String code, String source) throws Exception { String link = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; // 应用唯一标识 link = link.replace("APPID", heHeAppId); // 应用密钥AppSecret,在微信开放平台提交应用审核通过后获得 link = link.replace("SECRET", heHeAppSecret); // 获取的code参数 link = link.replace("CODE", code); // 发送授权链接,得到微信用户信息 String result = HttpRequest.sendGet(link); log.info(result); Map map = JSONObject.parseObject(result, Map.class); return map; } /** * 微信公众号获取access_token * * @return access_token */ public String getAccessToken() throws Exception { // String access_token = String.valueOf(redisService.get("access_token:"+crmAppId)); // // 过期后会得到"null"值,所以需判断字符串"null" // if (access_token != null && access_token.length() != 0 && !"null".equals(access_token)) { // return access_token; // } String link = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; link = link.replace("APPID", "wx0938e78f38bc203d"); link = link.replace("APPSECRET", "a563dd2c07c9c815a4e697c8b6cb73dc"); String result = HttpRequest.sendGet(link); log.info("微信公众号获取access_token>>>" + result); Map map = JSONObject.parseObject(result, Map.class); String access_token = (String) map.get("access_token"); // // 将token存入redis, access_token的有效期目前为2个小时(redis存1.5小时) // redisService.set("access_token:"+crmAppId, access_token, 5400L); return access_token; } /** * 微信公众号获取用户信息 * * @return */ public Map getUserInfo(String accessToken, String openId) throws Exception { String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN"; String userInfo = HttpRequest.sendGet(requestUrl); log.info("微信公众号授权用户数据>>>>>>>>>>>" + userInfo); Map map = JSONObject.parseObject(userInfo, Map.class); return map; } /** * 网页授权登录,获取用户信息(UnionID机制) */ public Map getUserInfoByWeb(String access_token, String openId) throws Exception { String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openId; String userInfo = HttpRequest.sendGet(requestUrl); Map map = JSONObject.parseObject(userInfo, Map.class); return map; } }