Java获取微信小程序code获取openid、session_key、unionid,获取授权信息解密获取手机号

前言

  在小程序的项目中,对小程序授权获取的code值进行解析是一个必要的操作,因为需要获取到其中的openid、session_key、unionid进行一个身份的验证。判断该用户是新用户或是其它操作(具体根据自己的业务需求修改就行)
  其中unionid需要主体账户绑定了小程序后才可以获取到。所以在没有绑定的时候,我们解析code是只能获取到openid和session_key两个参数的
	接下来我们开始操作一下,代码和详细操作如下👇

一、Java解析微信小程序code,获取openid、session_key、unionid

1、先写一个code解析的工具类

WechatUtils


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
// vo实体类参数
import com.entityVo.TestEntityVO ;
import com.utils.TestUtils;

import org.bouncycastle.util.encoders.Base64;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.TextUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.*;

@Slf4j(topic = "WechatUtils")
@Component
public class WechatUtil {
	private static final String appId = "*****";
	private static final String secret = "*x**x****";

	/**
	 * 获取小程序code换取openid、session_key
	 *
	 * @param code
	 * @return
	 */
	public static JSONObject getOpenId(String code) {

		String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId
				+ "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
		PrintWriter out = null;
		BufferedReader in = null;
		String line;
		StringBuffer stringBuffer = new StringBuffer();
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();

			// 设置通用的请求属性 设置请求格式
			//设置返回类型
			conn.setRequestProperty("contentType", "text/plain");
			//设置请求类型
			conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
			//设置超时时间
			conn.setConnectTimeout(1000);
			conn.setReadTimeout(1000);
			conn.setDoOutput(true);
			conn.connect();
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应    设置接收格式
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream(), "UTF-8"));
			while ((line = in.readLine()) != null) {
				stringBuffer.append(line);
			}
			JSONObject jsonObject = JSONObject.parseObject(stringBuffer.toString());
			return jsonObject;

		} catch (Exception e) {
			e.printStackTrace();
		}
		//使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return null;
	}
}

2、业务逻辑层的业务代码

(具体实体类自己根据自己的业务需求配置就行)
service

public interface WxOperationService{
	TestEntity getCodeInfo(TestEntityVO vo);
}

impl实现类

@Service
pulic class WxOperationServiceImpl implements WxOperationService{
	
	@Override
	public TestEntity getCodeInfo(TestEntityVO vo){
		TestEntity entity = new TestEntity;
		// 获取code数据
		JSONObject object = WechatUtils.getOpenId(vo.getCode())
		// json数据转换成字符串
		String openid = wx.get("openid").toString();
		String sessionkey = wx.get("session_key").toString();
		// 当主体账户绑定小程序后就可以获取到,未绑定无法获取
        String unionId="";
        if(!EmptyUtils.isEmpty(wx.get("unionid"))){
            unionId=wx.get("unionid").toString();
        }
        entity.setOpenId(openid);
        entity.setSessionKey(sessionkey);
        entity.setUnionId(unionid);
        // 是否需要获取手机号,true需要
        entity.setIsFlagPhone(true);
        System.out.println("openid:"+openid+",session_key:"+sessionkey+",unionid:"+unionid);
        // 返回参数
		return entity;
	}
}

👆这个代码已经可以解析出code信息,具体的业务流程自己去添加就ok


二、Java获取微信用户手机号

  在上面的代码中我们已经获取到了openid和session_key了,而code信息中是不能获取到用户的手机号码的,解析微信手机号的相关数据需要openid和session_key才行,所以在上面代码中,我将相关数据返回给了前端,前端将我传回的参数,还有第二次请求中的iv、encryptedData一起传回给后端,然后我们进行解密
接下来我们操作一下,代码如下👇

1、工具类中添加解密方法

还是我们之前的WechatUtils,在里面添加getPhone方法


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
// vo实体类参数
import com.entity.TestEntityVO;
import com.utils.TestUtils;

import org.bouncycastle.util.encoders.Base64;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.TextUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.*;

@Slf4j(topic = "WechatUtils")
@Component
public class WechatUtil {
	private static final String appId = "*****";
	private static final String secret = "********";

	/**
	 * 获取小程序code换取openid、session_key
	 *
	 * @param code
	 * @return
	 */
	public static JSONObject getOpenId(String code) {

		String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId
				+ "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
		PrintWriter out = null;
		BufferedReader in = null;
		String line;
		StringBuffer stringBuffer = new StringBuffer();
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();

			// 设置通用的请求属性 设置请求格式
			//设置返回类型
			conn.setRequestProperty("contentType", "text/plain");
			//设置请求类型
			conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
			//设置超时时间
			conn.setConnectTimeout(1000);
			conn.setReadTimeout(1000);
			conn.setDoOutput(true);
			conn.connect();
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应    设置接收格式
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream(), "UTF-8"));
			while ((line = in.readLine()) != null) {
				stringBuffer.append(line);
			}
			JSONObject jsonObject = JSONObject.parseObject(stringBuffer.toString());
			return jsonObject;

		} catch (Exception e) {
			e.printStackTrace();
		}
		//使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return null;
	}
}

public static Map<String, Object> getPhoneNumber(TestEntityVO vo) {
		Map<String,Object> map=new HashMap<>();
		String openid= vo.getWechatOpenId();
		String session_key = vo.getSessionKey();
		if (!EmptyUtils.isEmpty(openid)) {

			if(EmptyUtils.isEmpty(session_key)){
				return null;
			}
			map.put("openid",openid);
			// 被加密的数据
			byte[] dataByte = Base64.decode(vo.getEncryptedData());
			// 加密秘钥
			byte[] keyByte = Base64.decode(session_key);
			// 偏移量
			byte[] ivByte = Base64.decode(vo.getIv());
			try {
				// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
				int base = 16;
				String result = null;
				if (keyByte.length % base != 0) {
					int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
					byte[] temp = new byte[groups * base];
					Arrays.fill(temp, (byte) 0);
					System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
					keyByte = temp;
				}
				// 初始化
				Security.addProvider(new BouncyCastleProvider());
				Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
				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) {
					result = new String(resultByte, "UTF-8");
					JSONObject jsonObject = JSONObject.parseObject(result);
					map.put("param",jsonObject);
					return map;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}

2、业务逻辑层代码

service

public interface WxOperationService{
	TestEntity getCodeInfo(TestEntityVO vo);
	
	TestEntityDTO getCodeInfo(TestEntityVO vo);
}

impl实现类

@Override
	public TestEntityDTO getCodeInfo(TestEntityVO vo) throws CoBusinessException {
	TestEntityDTO dto = new TestEntityDTO ;
	Map<String, Object> map = WechatUtil.getPhoneNumber(param);
		if (EmptyUtils.isEmpty(map)) {
			throw new CoBusinessException(CoReturnFormat.WECHAT_ERROR);
		}
		String phone = "";
		Object phoneNumber = map.get("param");
		String jsonString = JSONObject.toJSONString(phoneNumber);
		JSONObject obj = JSONObject.parseObject(jsonString);
		if (!EmptyUtils.isEmpty(jsonString)) {
			phone = obj.get("phoneNumber").toString();
		}
		dto.setPhone(phone);
		return dto;
}

👆以上就是本次的笔记了,大家有需要用的自取,有用记得点个赞噢

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值