如何用JAVA解密微信小程序获取的手机号

如何用JAVA解密微信小程序获取的手机号

1、加解密工具类

package ***;

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;

public class AES {
    // 算法名
    public static final String KEY_NAME = "AES";
    // 加解密算法/模式/填充方式
    // ECB模式只用密钥即可对数据进行加密解密,CBC模式需要添加一个iv
    public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";

    /**
     * 微信 数据解密
* 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充
* 对称解密的目标密文:encrypted=Base64_Decode(encryptData)
* 对称解密秘钥:key = Base64_Decode(session_key),aeskey是16字节
* 对称解密算法初始向量:iv = Base64_Decode(iv),同样是16字节
* * @param encrypted 目标密文 * @param session_key 会话ID * @param iv 加密算法的初始向量 */ public static String wxDecrypt(String encrypted, String session_key, String iv) { String json = null; byte[] encrypted64 = Base64.decodeBase64(encrypted); byte[] key64 = Base64.decodeBase64(session_key); byte[] iv64 = Base64.decodeBase64(iv); byte[] data; try { init(); json = new String(decrypt(encrypted64, key64, generateIV(iv64))); } catch (Exception e) { e.printStackTrace(); } return json; } /** * 初始化密钥 */ public static void init() throws Exception { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyGenerator.getInstance(KEY_NAME).init(128); } /** * 生成iv */ public static AlgorithmParameters generateIV(byte[] iv) throws Exception { // iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0 // Arrays.fill(iv, (byte) 0x00); AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME); params.init(new IvParameterSpec(iv)); return params; } /** * 生成解密 */ public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv) throws Exception { Key key = new SecretKeySpec(keyBytes, KEY_NAME); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); // 设置为解密模式 cipher.init(Cipher.DECRYPT_MODE, key, iv); return cipher.doFinal(encryptedData); } }

2、代码中应用

在小程序前端通过wx.login获得用户授权码code以后,我们用appid、appSecret、code请求微信的如下接口:

请求方式:http get 
接口地址:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

注意:APPID、SECRET、JSCODE即为需要传的参数appid、appSecret、code,顺序依次对应。

  • 以下是一个解密微信小程序获取的手机号的方法
    public DecodeTelResVo decodeTel(DecodeTelReqVo reqVo) throws Exception {
        DecodeTelResVo resVo=new DecodeTelResVo();
        Map params=new HashMap();
        params.put("APPID", reqVo.getAppId());
        params.put("SECRET", reqVo.getSecret());
        params.put("JSCODE", reqVo.getJsCode());
        String url= backUrlProperty.getWechatopenidUrl()+"/sns/jscode2session?appid={APPID}&secret={SECRET}&js_code={JSCODE}&grant_type=authorization_code";
        String jsonStr = restTemplate.getForObject(url, String.class,params);
        System.out.println("调用微信接口返回数据:"+jsonStr);
        if(!jsonStr.contains("session_key")) {
            throw new Exception("用户信息获取失败,请重新打开小程序!_9999");
        }
        
        JSONObject jsonObj=JSONObject.parseObject(jsonStr);
        if(jsonObj==null) {
            throw new Exception("用户信息获取失败,请重新打开小程序!_9999");
        }
        
        String tel="";
        try {
            System.out.println("解密前的手机号:"+reqVo.getTel());
            tel = AES.wxDecrypt(reqVo.getTel(), jsonObj.getString("session_key"), reqVo.getIv());
            System.out.println("解密后的手机号:"+reqVo.getTel());
        } catch (Exception e) {
            throw new Exception("用户信息获取失败,请重新打开小程序!_9999");
        }
        resVo.setSuccess(true);
        resVo.setTel(tel);
        resVo.setErrorCode("200");
        return resVo;
    }

注意文中的get请求调接口的传参方式,我最初做的时候就在这出了错导致屡次失败。

  • 方法的请求实体类:
package ***;

import org.hibernate.validator.constraints.NotEmpty;

import com.shibo.etc.net.issuer.server.issuer.vo.base.BaseReqVo;

import io.swagger.annotations.ApiModelProperty;

public class DecodeTelReqVo extends BaseReqVo {
	
    @ApiModelProperty("加密的手机号")
    @NotEmpty(message = "用户信息获取失败,请重新打开小程序")
    private String tel;
    
    @ApiModelProperty("APPID")
    @NotEmpty(message = "用户信息获取失败,请重新打开小程序")
    private String appId;
    
    @ApiModelProperty("SECRET")
    @NotEmpty(message = "用户信息获取失败,请重新打开小程序")
    private String secret;
    
    @ApiModelProperty("JSCODE")
    @NotEmpty(message = "用户信息获取失败,请重新打开小程序")
    private String jsCode;
    
    @ApiModelProperty("iv是从小程序获取到的加密参数")
    @NotEmpty(message = "用户信息获取失败,请重新打开小程序")
    private String iv;

    /**
     * @return the tel
     */
    public String getTel() {
        return tel;
    }

    /**
     * @param tel the tel to set
     */
    public void setTel(String tel) {
        this.tel = tel;
    }

    /**
     * @return the appId
     */
    public String getAppId() {
        return appId;
    }

    /**
     * @param appId the appId to set
     */
    public void setAppId(String appId) {
        this.appId = appId;
    }

    /**
     * @return the secret
     */
    public String getSecret() {
        return secret;
    }

    /**
     * @param secret the secret to set
     */
    public void setSecret(String secret) {
        this.secret = secret;
    }

    /**
     * @return the jsCode
     */
    public String getJsCode() {
        return jsCode;
    }

    /**
     * @param jsCode the jsCode to set
     */
    public void setJsCode(String jsCode) {
        this.jsCode = jsCode;
    }

    /**
     * @return the iv
     */
    public String getIv() {
        return iv;
    }

    /**
     * @param iv the iv to set
     */
    public void setIv(String iv) {
        this.iv = iv;
    }

    /**
     * 开发人员: wy
     * @return
     */
    @Override
    public String toString() {
        return "DecodeTelReqVo [tel=" + tel + ", appId=" + appId + ", secret=" + secret + ", jsCode=" + jsCode + ", iv="
                + iv + "]";
    }
}

  • 方法的响应实体类:
package ***;

import com.shibo.etc.net.issuer.server.issuer.vo.base.BaseResVo;

import io.swagger.annotations.ApiModelProperty;

public class DecodeTelResVo extends BaseResVo {
	@ApiModelProperty("解密后的手机号")
	private String tel;

    /**
     * @return the tel
     */
    public String getTel() {
        return tel;
    }

    /**
     * @param tel the tel to set
     */
    public void setTel(String tel) {
        this.tel = tel;
    }

    /**
     * 开发人员: wy
     * @return
     */
    @Override
    public String toString() {
        return "DecodeTelResVo [tel=" + tel + "]";
    }
}

你可能感兴趣的:(JAVA)