2025 Java 微信小程序根据code获取openid,二次code获取手机号【工具类】拿来就用

news2025/5/17 13:32:00

一、controller调用 


/**
 * 登录
 *
 * @author jiaketao
 * @since 2024-04-10
 */
@RestController
@RequestMapping("/login")
public class LoginController {

    /**
     * 【小程序】登录获取session_key和openid
     *
     * @param code 前端传code
     * @return
     */
    @GetMapping("/getWXSessionKey")
    public 自己的业务返回体 getWXSessionKey(String code) {
        //根据前端传来的code,调用微信的接口获取到当前用户的openid
        JSONObject jsonObject = WeChatLoginUtils.getWXSessionKey(code);
        String openId = jsonObject.getString("openid");
        //自己的业务逻辑...    }

    /**
     * 【小程序】获取手机号
     *
     * @param code 第二次的code
     * @return
     */
    @GetMapping("/getWXPhoneInfo")
    public String getWXPhoneInfo(String code) throws IOException {
        return  WeChatLoginUtils.getWXPhoneInfo(code).getJSONObject("phone_info").getString("phoneNumber");
    }

  
}

二、封装的工具类

 1、微信登录核心工具类:WeChatLoginUtils

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;


/**
 * 微信小程序登录工具类
 *
 * @author jiaketao
 * @since 2024-04-10
 */
public class WeChatLoginUtils {

    /**
     * 1.获取session_key
     *
     * @param code 微信小程序的第一个code
     * @return
     */
    public static JSONObject getWXSessionKey(String code) {
        String urlResult = HttpRequestUrlUtil.httpGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + WxConstUtils.WX_OPEN_APPLET_APPID + "&secret=" + WxConstUtils.WX_OPEN_APPLET_SECRET + "&js_code=" + code + "&grant_type=authorization_code");
        // 转为json
        JSONObject jsonObject = JSON.parseObject(urlResult);
        return jsonObject;
    }

    /**
     * 2.获取access_token
     *
     * @return
     */
    public static JSONObject getWXAccessToken() {
        String urlResult = HttpRequestUrlUtil.httpGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + WxConstUtils.WX_OPEN_APPLET_APPID + "&secret=" + WxConstUtils.WX_OPEN_APPLET_SECRET);
        // 转为json
        JSONObject jsonObject = JSON.parseObject(urlResult);
        return jsonObject;
    }

    /**
     * 获取手机号
     *
     * @param code 微信小程序的第2个code
     * @return
     */
    public static JSONObject getWXPhoneInfo(String code) throws IOException {
        // 调用 2.获取access_token
        String access_token = getWXAccessToken().getString("access_token");
        String getPhoneNumberUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + access_token;
        JSONObject json = new JSONObject();
        json.put("code", code);
        // post请求
        json = HttpRequestUrlUtil.postResponse(getPhoneNumberUrl, json);
        return json;
    }


}

2、配置文件:WxConstUtils

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


/**
 * 微信登录支付相关字段工具类
 *
 * @author zhaoyan
 * @since 2024-04-10
 */
@Component
public class WxConstUtils implements InitializingBean {
    // 小程序 appid
    public static String WX_OPEN_APPLET_APPID;
    // 小程序 secret密钥
    public static String WX_OPEN_APPLET_SECRET;
    // 商户号
    public static String WX_OPEN_MCHID;
    // 密钥key
    public static String WX_OPEN_KEY;

    //从配置文件获取以上内容的配置值
    // 小程序appid
    @Value("${wx.open.applet.app_id}")
    private String appletAppId;

    //小程序 secret密钥
    @Value("${wx.open.applet.secret}")
    private String appletSecret;

    // 商户号
    @Value("${wx.open.mch_id}")
    private String mchId;

    // 密钥key
    @Value("${wx.open_key}")
    private String key;

    @Override
    public void afterPropertiesSet() throws Exception {
        WX_OPEN_APPLET_APPID = appletAppId;
        WX_OPEN_APPLET_SECRET = appletSecret;
        WX_OPEN_MCHID = mchId;
        WX_OPEN_KEY = key;
    }
}

3、http请求工具类:HttpRequestUrlUtil

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;


/**
 * http请求
 *
 * @author jiaketao
 * @since 2024-04-10
 */
public class HttpRequestUrlUtil {

    /**
     * post请求
     *
     * @param url
     * @param object
     * @return
     */
    public static String httpPost(String url, JSONObject object) {

        String result = "";

        // 使用CloseableHttpClient和CloseableHttpResponse保证httpcient被关闭
        CloseableHttpClient httpClient;

        CloseableHttpResponse response;

        HttpPost httpPost;

        UrlEncodedFormEntity entity;

        try {

            httpClient = HttpClients.custom().build();

            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

            Set<String> keySets = object.keySet();

            Iterator<String> keys = keySets.iterator();

            while (keys.hasNext()) {

                String key = keys.next();

                nameValuePairs.add(new BasicNameValuePair(key, object.getString(key)));
            }

            entity = new UrlEncodedFormEntity(nameValuePairs, "utf-8");

            httpPost = new HttpPost(url);

            httpPost.setEntity(entity);

            //设置超时时间
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000).build();

            httpPost.setConfig(requestConfig);

            response = httpClient.execute(httpPost);

            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

                result = EntityUtils.toString(response.getEntity());
            }

        } catch (ClientProtocolException e) {

        } catch (IOException e) {

        } catch (Exception e) {

        } finally {

        }

        return result;
    }

    /**
     * get请求
     *
     * @param url
     * @return
     */
    public static String httpGet(String url) {

        String result = "";

        // 使用CloseableHttpClient和CloseableHttpResponse保证httpcient被关闭
        CloseableHttpClient httpClient = null;

        CloseableHttpResponse response = null;

        try {

            httpClient = HttpClients.custom().build();

            response = httpClient.execute(new HttpGet(url));

            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {

                result = EntityUtils.toString(response.getEntity());
            }

        } catch (ClientProtocolException e) {
        } catch (IOException e) {
        } catch (Exception e) {
        } finally {

        }

        return result;
    }

    /**
     * post请求封装 参数为?a=1&b=2&c=3
     *
     * @param path 接口地址
     * @param Info 参数
     * @return
     * @throws IOException
     */
    public static JSONObject postResponse(String path, String Info) throws IOException {

        //1, 得到URL对象
        URL url = new URL(path);

        //2, 打开连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        //3, 设置提交类型
        conn.setRequestMethod("POST");

        //4, 设置允许写出数据,默认是不允许 false
        conn.setDoOutput(true);
        conn.setDoInput(true);//当前的连接可以从服务器读取内容, 默认是true

        //5, 获取向服务器写出数据的流
        OutputStream os = conn.getOutputStream();
        //参数是键值队  , 不以"?"开始
        os.write(Info.getBytes());
        //os.write("googleTokenKey=&username=admin&password=5df5c29ae86331e1b5b526ad90d767e4".getBytes());
        os.flush();
        //6, 获取响应的数据
        //得到服务器写回的响应数据
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
        String str = br.readLine();
        JSONObject json = JSONObject.parseObject(str);

        System.out.println("响应内容为:  " + json);

        return json;
    }

    /**
     * post请求封装 参数为{"a":1,"b":2,"c":3}
     *
     * @param path 接口地址
     * @param Info 参数
     * @return
     * @throws IOException
     */
    public static JSONObject postResponse(String path, JSONObject Info) throws IOException {
        HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(path);

        post.setHeader("Content-Type", "application/json");
        post.addHeader("Authorization", "Basic YWRtaW46");
        String result = "";

        try {
            StringEntity s = new StringEntity(Info.toString(), "utf-8");
            s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
            post.setEntity(s);

            // 发送请求
            HttpResponse httpResponse = client.execute(post);

            // 获取响应输入流
            InputStream inStream = httpResponse.getEntity().getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "utf-8"));
            StringBuilder strber = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null)
                strber.append(line + "\n");
            inStream.close();

            result = strber.toString();
            System.out.println(result);

            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                System.out.println("请求服务器成功,做相应处理");
            } else {
                System.out.println("请求服务端失败");
            }

        } catch (Exception e) {
            System.out.println("请求异常");
            throw new RuntimeException(e);
        }

        return JSONObject.parseObject(result);
    }
}

三、maven依赖:pom.xml

<!--  导入Json格式化依赖 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

<!--  导入Apache HttpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.14</version>
</dependency>


<!-- Spring Boot Starter (包含 Spring Core, Spring Beans, Spring Context 等) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.7.18</version> <!-- 或使用最新版本 -->
</dependency>

<!-- 如果需要 @Value 注解读取配置文件 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-config</artifactId>
    <version>2.7.18</version>
</dependency>

四、配置文件:application.properties

#wechat  Config
wx.open.applet.app_id=自己的appid
wx.open.applet.secret=自己的secret密钥
#wx.open.applet.sub_app_id=
wx.open.mch_id=
wx.open_key=
wx.open.sub_mch_id=

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2377698.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

window 显示驱动开发-分页视频内存资源

与 Microsoft Windows 2000 显示驱动程序模型不同&#xff0c;Windows Vista 显示驱动程序模型允许创建比可用物理视频内存总量更多的视频内存资源&#xff0c;然后根据需要分页进出视频内存。 换句话说&#xff0c;并非所有视频内存资源都同时位于视频内存中。 GPU 的管道中可…

【笔记】记一次PyCharm的问题反馈

#工作记录 最近更新至 PyCharm 社区版的最新版本后&#xff0c;我遇到了多个影响使用体验的问题。令人感到不便的是&#xff0c;一些在旧版本中非常便捷的功能&#xff0c;在新版本中却变得操作复杂、不够直观。过去&#xff0c;我一直通过 PyCharm 内置的故障报告与反馈机制反…

uniapp中vue3和pinia安装依赖npm install失败

目录 一、问题描述 二、问题原因 三、问题解析及解决方案 一、问题描述 用uni-app开发小程序的时候&#xff0c;使用了vue3pinia,安装依赖的时候发现vue和pinia的版本问题&#xff0c;安装失败&#xff0c; npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve np…

DBF Converter:高效转换DBF文件,满足多样化数据处理需求

DBF Converter 是一款功能强大的数据转换工具&#xff0c;专为需要将DBF文件转换为其他格式的用户设计。它支持将DBF文件转换为CSV、Excel、HTML、SQL等多种常见格式&#xff0c;满足用户在不同场景下的数据处理需求。无论是数据迁移、报表生成还是日常数据处理&#xff0c;DBF…

Jmeter 安装包与界面汉化

Jmeter 安装包&#xff1a; 通过网盘分享的文件&#xff1a;CSDN-apache-jmeter-5.5 链接: https://pan.baidu.com/s/17gK98NxS19oKmkdRhGepBA?pwd1234 提取码: 1234 Jmeter界面汉化&#xff1a;

【C++】 —— 笔试刷题day_29

一、排序子序列 题目解析 一个数组的连续子序列&#xff0c;如果这个子序列是非递增或者非递减的&#xff1b;这个连续的子序列就是排序子序列。 现在给定一个数组&#xff0c;然后然我们判断这个子序列可以划分成多少个排序子序列。 例如&#xff1a;1 2 3 2 2 1 可以划分成 …

MongoTemplate 基础使用帮助手册

前言 MongoDB 是一种流行的 NoSQL 数据库&#xff0c;适合存储大量的非结构化数据。MongoTemplate 是 Spring Data MongoDB 中的一个核心组件&#xff0c;它提供了一组丰富的 API 来与 MongoDB 进行交互。它封装了许多常见的数据库操作&#xff0c;使开发者能够轻松执行 CRUD 操…

图像处理:预览并绘制图像细节

前言 因为最近在搞毕业论文的事情&#xff0c;要做出一下图像细节对比图&#xff0c;所以我这里写了两个脚本&#xff0c;一个用于框选并同时预览图像放大细节&#xff0c;可显示并返回框选图像的坐标&#xff0c;另外一个是输入框选图像的坐标并将放大的细节放置在图像中&…

力扣热题——最长相邻不相等子序列 |

题目要求从字符串数组 words 中选出一个最长的子序列&#xff0c;使得该子序列中相邻字符串对应的 groups 数组中的值不同。通过贪心算法&#xff0c;可以高效地解决该问题。具体步骤为&#xff1a;初始化一个结果列表&#xff0c;遍历 words 数组&#xff0c;检查当前字符串的…

ssti刷刷刷

[NewStarCTF 公开赛赛道]BabySSTI_One 测试发现过滤关键字&#xff0c;但是特殊符号中括号、双引号、点都能用 可以考虑拼接或者编码&#xff0c;这里使用拼接 ?name{{()["__cla"~"ss__"]}}?name{{()["__cla"~"ss__"]["__ba&…

java+selenum专题(一)

环境搭建部署篇-> 1.简介 java版的selenium&#xff0c;介绍一下java selenium自动化测试。大致和pythonselenium自动化测试差不多。基于java和selenium做自动化测试&#xff0c;因此你必须会搭建基本的开发环境&#xff0c;掌握python基本的语法和一个IDE来进行开发&…

[逆向工程]DebugView捕获WPS日志?解析未运行WPS时Shell扩展加载的原因与解决方案(二十五)

[逆向工程]DebugView捕获WPS日志&#xff1f;解析未运行WPS时Shell扩展加载的原因与解决方案&#xff08;二十五&#xff09; 引言&#xff1a;一个“幽灵”般的日志问题 你是否在使用 DebugView 排查系统问题时&#xff0c;发现日志中频繁出现 WPS 相关模块&#xff08;如 k…

ACM模式用Scanner和System.out超时的解决方案和原理

Hi~&#xff01;这里是奋斗的明志&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f331;&#x1f331;个人主页&#xff1a;奋斗的明志 &#x1f331;&#x1f331;所属专栏&#xff1a;笔试强训 &#x1f4da;本系列文章为个人学…

Java注解详解:从入门到实战应用篇

1. 引言 Java注解&#xff08;Annotation&#xff09;是JDK 5.0引入的一种元数据机制&#xff0c;用于为代码提供附加信息。它广泛应用于框架开发、代码生成、编译检查等领域。本文将从基础到实战&#xff0c;全面解析Java注解的核心概念和使用场景。 2. 注解基础概念 2.1 什…

QML 属性动画、行为动画与预定义动画

目录 引言相关阅读本文使用的动画属性工程结构示例解析示例1&#xff1a;属性动画应用示例2&#xff1a;行为动画实现示例3&#xff1a;预定义动画 总结工程下载 引言 QML动画系统为界面元素提供了流畅的过渡效果。本文通过三个示例&#xff0c;结合属性动画(PropertyAnimatio…

window nvidia-smi命令 Failed to initialize NVML: Unknown Error

如果驱动目录下的可以执行&#xff0c;那可能版本原因 "C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi"复制"C:\Program Files\NVIDIA Corporation\NVSMI\nvidia-smi.exe"替换 C:\Windows\System32\nvidia-smi.exe 或者 把C:\Windows\System3…

自学嵌入式 day19-数据结构 链表

二、线性表的链式存储 1.特点&#xff1a; &#xff08;1&#xff09;线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素&#xff0c;存储单元可以是连续的&#xff0c;也可以不连续。可以被存储在任意内存未被占用的位置上。 &#xff08;2&#xff09;所以…

东芝第3代SiC MOSFET助于降低应用中电源损耗

功率器件是管理和降低各种电子设备电能功耗以及实现碳中和社会的重要元器件。由于与比硅材料相比&#xff0c;碳化硅具有更高的电压和更低的损耗&#xff0c;因此碳化硅&#xff08;SiC&#xff09;被广泛视为下一代功率器件的材料。虽然碳化硅功率器件目前主要用于列车逆变器&…

PD 分离推理的加速大招,百度智能云网络基础设施和通信组件的优化实践

为了适应 PD 分离式推理部署架构&#xff0c;百度智能云从物理网络层面的「4us 端到端低时延」HPN 集群建设&#xff0c;到网络流量层面的设备配置和管理&#xff0c;再到通信组件和算子层面的优化&#xff0c;显著提升了上层推理服务的整体性能。 百度智能云在大规模 PD 分离…

官方 Elasticsearch SQL NLPChina Elasticsearch SQL

官方的可以在kibana 控制台上进行查询&#xff1a; POST /_sql { “query”: “SELECT client_ip, status FROM logs-2024-05 WHERE status 500” } NLPChina Elasticsearch SQL就无法以在kibana 控制台上进行查询&#xff0c;但是可以使用postman接口进行查询&#xff1a;