Java 微信小程序登录

1.修改 appId、secret 为自己的
 

package com.rongtong.modules.app.controller;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rongtong.common.exception.RRException;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Arrays;

@RestController
public class WxLoginController {

    // 小程序 appId
    private final String appid = "wx75c9572*********";
    // 小程序 appSecret
    private final String secret = "57fc7766188f86af2e285**********";


    // 算法名称
    static final String KEY_ALGORITHM = "AES";
    // 加解密算法/模式/填充方式 
    static final String algorithmStr = "AES/CBC/PKCS7Padding";
    private static Key key;
    private static Cipher cipher;


    @Data
    public static class WxLoginVo {
        //公众号或小程序授权cod
        private String code;

        //包括敏感数据在内的完整用户信息的加密数据
        private String encryptedData;

        //加密算法的初始向量
        private String iv;
    }


    @Data
    public static class WxClient {
        // 用户id 会员存在则返回
        private Integer cid;
        // 用户唯一标识
        private String openId;
        // 用户昵称
        private String nickName;
        // 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
        private Integer gender;
        // 用户头像
        private String avatarUrl;
        // 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回,详见 UnionID 机制说明。
        private String unionid;
        // 会话密钥
        private String sessionKey;
    }


    /**
     * 小程序登录
     */
    @PostMapping("/wx/login")
    public void wxLogin(@RequestBody WxLoginVo vo) {

        String json = this.codeSession(vo.getCode());
        WxClient client = JSON.parseObject(json, WxClient.class);

        String openId = client.getOpenId();
        System.out.println(openId);

        String unionid = client.getUnionid();
        System.out.println(unionid);

        // 用户信息获取不到头像昵称了
// https://developers.weixin.qq.com/community/develop/doc/00022c683e8a80b29bed2142b56c01
        WxClient program = this.getProgram(client.getSessionKey(), vo.getEncryptedData(), vo.getIv());
        
        System.out.println(program);

    }


    private String codeSession(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
        String result = HttpUtil.get(url);
        JSONObject object = JSONObject.parseObject(result);
        return object.toString();

    }


    /**
     * 获取小程序用户对象
     *
     * @param sessionkey
     * @param encryptedData
     * @param iv
     * @return
     */
    public WxClient getProgram(String sessionkey, String encryptedData, String iv) {
        String result = getStr(encryptedData, sessionkey, iv);
        WxClient client = JSON.parseObject(result, WxClient.class);
        return client;
    }


    private static String getStr(String encryptedData, String keys, String iv) {
        byte[] data = decrypt(encryptedData, keys, iv);
        String dataStr = "";
        try {
            dataStr = new String(data, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RRException("授权失败,请重新授权");
        }
        return dataStr;
    }


    /**
     * 解密方法
     *
     * @param encryptedDataStr 要解密的字符串
     * @param keyBytesStr      解密密钥
     * @return
     */
    public static byte[] decrypt(String encryptedDataStr, String keyBytesStr, String ivStr) {
        byte[] encryptedText = null;
        byte[] encryptedData = null;
        byte[] sessionkey = null;
        byte[] iv = null;

        try {
            sessionkey = Base64.decodeBase64(keyBytesStr);
            encryptedData = Base64.decodeBase64(encryptedDataStr);
            iv = Base64.decodeBase64(ivStr);

            init(sessionkey);

            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new RRException("授权失败,请重新授权");
        }
        return encryptedText;
    }

    public static void init(byte[] keyBytes) {

        // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
        int base = 16;
        if (keyBytes.length % base != 0) {
            int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
            keyBytes = temp;
        }
        // 初始化
        Security.addProvider(new BouncyCastleProvider());
        // 转化成JAVA的密钥格式
        key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

景立

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值