All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.boommanpro.wechat.WeChatService Maven / Gradle / Ivy

package cn.boommanpro.wechat;


import cn.boommanpro.wechat.bean.Code2Session;
import cn.boommanpro.wechat.bean.WeChatAccountInfo;
import cn.boommanpro.wechat.bean.WeChatDecryptForm;
import cn.boommanpro.wechat.bean.WeChatLoginForm;
import cn.boommanpro.wechat.bean.WeChatProperties;
import cn.boommanpro.wechat.exception.WeChatDecryptException;
import cn.boommanpro.wechat.util.CommonUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.log4j.Log4j2;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.spec.InvalidParameterSpecException;
import java.util.Base64;

/**
 * @author BoomMan  [email protected]  WeChatService
 */
@Log4j2
public class WeChatService {
    private final static String AES = "AES";

    private final String webAccessTokenHttps = "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code";

    @Autowired
    private WeChatProperties weChatProperties;

    static {

        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 核心方法
     *
     * @param weChatLoginForm 请求地址
     * @return 返回用户信息
     */
    public WeChatAccountInfo decryptWeChatLoginForm(WeChatLoginForm weChatLoginForm) {
        Code2Session code2Session = decryptWeChatLoginCodeSession(weChatLoginForm.getCode());
        WeChatDecryptForm weChatDecryptForm = new WeChatDecryptForm(weChatLoginForm.getEncryptedData(), weChatLoginForm.getIv(), code2Session.getSessionKey());
        WeChatAccountInfo weChatAccountInfo = JSON.parseObject(decrypt(weChatDecryptForm), WeChatAccountInfo.class);
        weChatAccountInfo.setOpenId(code2Session.getOpenId());
        weChatAccountInfo.setUnionId(code2Session.getOpenId());
        return weChatAccountInfo;
    }

    public Code2Session decryptWeChatLoginCodeSession(String code) {
        String requestUrl = getWebAccess(code);
        Code2Session code2Session = CommonUtil.httpsRequest(requestUrl, "GET", null).toJavaObject(Code2Session.class);
        if (code2Session.getErrcode() != Code2Session.SUCCESS) {
            log.error("解密用户数据异常: from code:{}, errorCode:{}, code2Session:{}", code, code2Session.getErrcode(), code2Session.getErrmsg());
            throw new WeChatDecryptException(String.format("code:%s, errmsg:%s", code2Session.getErrmsg(), code2Session.getErrmsg()));
        }
        return code2Session;
    }


    private String getWebAccess(String code) {
        return String.format(webAccessTokenHttps,
                weChatProperties.getAppId(),
                weChatProperties.getSecret(),
                code);
    }


    private String decrypt(WeChatDecryptForm weChatDecryptForm) {
        //对传入信息进行处理
        String iv = weChatDecryptForm.getIv().replaceAll(" ", "+");
        String encryptedData = weChatDecryptForm.getEncryptedData().replaceAll(" ", "+");
        String sessionKey = weChatDecryptForm.getSessionKey().replaceAll(" ", "+");
        Base64.Decoder decoder = Base64.getDecoder();
        try {

            byte[] content = decoder.decode(encryptedData.getBytes(StandardCharsets.UTF_8));
            byte[] keyByte = decoder.decode(sessionKey.getBytes(StandardCharsets.UTF_8));
            byte[] ivByte = decoder.decode(iv.getBytes(StandardCharsets.UTF_8));
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec sKeySpec = new SecretKeySpec(keyByte, AES);
            AlgorithmParameters params = AlgorithmParameters.getInstance(AES);
            params.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, params);
            byte[] decryptBytes = cipher.doFinal(content);
            if (null != decryptBytes && decryptBytes.length > 0) {
                return new String(decryptBytes, StandardCharsets.UTF_8);
            }
            return null;
        } catch (NoSuchAlgorithmException | NoSuchProviderException | IllegalBlockSizeException |
                 InvalidParameterSpecException | BadPaddingException | NoSuchPaddingException |
                 InvalidAlgorithmParameterException | InvalidKeyException e) {
            return e.toString();
        }
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy