当前位置: 首页 > 工具软件 > Openid4j > 使用案例 >

IDEA+SpringBoot获取微信小程序openId和session_key

卫俊力
2023-12-01

按照惯例,先上官网链接 传送门

很多入门小伙伴可能看不懂官网给的图解,这里简单解释下
1. 从小程序端,用户授权wx.login(),得到 code
2. 在小程序端,拿着 code,给到自己的后台服务器
3. 在自己后台, 拿着前台传来的code,和自己的AppId,Secret,去请求微信服务接口
4. 微信服务接口,把用户的openId 和 session_key返回给你的后台服务器
5. 拿着返回的 openId 去开发后续的用户登录程序.
6. 如何获取 appId和Secret,请看文末
获取流程如下:
- 前端(小程序端)
- 	- user.wxml
- 	- user.js
- 	- app.js
- 后端(开发者服务器端)
- 	- 在pom.xml中导入jar包
- 	- 准备参数(AppId & secret) 
- 	- Ctrl+C+V 工具包
-	- 执行主要功能-获取openId
-	- 将获取到的openId做登录业务处理

查看自己的 AppId和Secret 传送门

小程序前端

在app.js页面中,增加自己的后台地址

  globalData: {
    userInfo: null,
    base_url: "http://localhost:8080"
  }

在user.wxml中,写上简陋的用户信息

<!--pages/user/user.wxml-->
<view class="container">
  <view class="userinfo">
    <!-- 如果可以使用用户信息,则显示用户信息 -->
    <block wx:if="{{canIUseOpenData}}">
      <view class="userinfo-avatar" bindtap="bindViewTap">
        <open-data type="userAvatarUrl" ></open-data>
      </view>
      <view class="userinfo-nickname">
        <open-data type="userNickName"></open-data>
      </view>
    </block>
    <!-- 反之, 显示按钮, 按钮用于授权登录用户信息 -->
    <block wx:else="{{!hasUserInfo}}">
      <button bindtap="login" >授权登录</button>
    </block>
  </view>
</view>

user.js

// pages/user/user.js
const app = getApp()
Page({

  /**
   * 页面的初始数据
   */
  data: { 
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo'),
    canIUseGetUserProfile: false,
    canIUseOpenData: false// wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    
  },

  login(){
    console.log("进入login方法");
    if(false){
      // 如果缓存中存在用户信息, 将缓存的数据赋值到userinfo中
    }
    wx.login({
      success(e){
        console.log(e.code);
        console.log(app.globalData);
        wx.request({
          url: app.globalData.base_url + '/wechat/getUserInfo',
          method: 'POST',
          header: {
            'content-type': 'application/x-www-form-urlencoded'
          },
          data: {
            code: e.code
          },
          success: (r) => {
            console.log("login() => wx.login => 用code换取登录信息请求成功!");
            console.log(r.data);
            const userInfo = r.data.object
            // 将返回的数据保存到全局的缓冲中,方便其他页面使用
            // wx.setStorage({ key: 'userInfo', data: userInfo }) 
            
          },
          fail: (res) => {
            console.warn("login() => wx.login => 用code换取登录信息请求失败");
          },
          complete: (res) => {

          },
        })

      }
    })
    // wx.openSetting({
    //   withSubscriptions: true, 
    // })
  }

开发者服务器(后端)

在pom.xml中导入jar包

<dependencies>
		<!--  ... 省略掉的其他jar包 ...  -->
		
        <!-- httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.3.5</version>
        </dependency>

        <!-- json -->
        <!--https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.49</version>
        </dependency>

    </dependencies>

在controller包的同级目录中新建util包(若已存在util就跳过)
在 util 包下,新建 wechat包和http包
wechat包下创建类,命名为: WeChatConfig
更改appid和secret为自己的

package com.leo.自己的项目域名.util.wechat;

public class WeChatConfig {
    // 请求网址
    public static final String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
    // 你的微信AppId
    public static final String WX_LOGIN_APPID = "自己的appidwxxxxxxb13";
    // 你的微信SECRET
    public static final String WX_LOGIN_SECRET = "自己的SECRET-33b1720a396a090";
    // 固定参数
    public static final String WX_LOGIN_GRANT_TYPE = "authorization_code";
}

在http包下创建工具类,命名为 HttpClientUtil
注意引入的包

package com.leo.自己的项目名.util.http;

import org.apache.http.NameValuePair;
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.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpClientUtil {

    public static String doGet(String url, Map<String, String> param) {

        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();

        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();

            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);

            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }

    public static String doGet(String url) {
        return doGet(url, null);
    }

    public static String doPost(String url, Map<String, String> param) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return resultString;
    }

    public static String doPost(String url) {
        return doPost(url, null);
    }

    public static String doPostJson(String url, String json) {
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return resultString;
    }
}

在controller包下创建类,命名为: WeChatController
类中方法的返回类型是自己定义的返回值类型,替换为自己的返回值即可

package com.leo.自己项目名.controller;

import com.alibaba.fastjson.JSONObject;
import com.leo.自己项目名.pojo.Result;
import com.leo.自己项目名.util.http.HttpClientUtil;
import com.leo.自己项目名.util.wechat.WeChatConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController	// 控制器类的注解
@Slf4j		// lombok的日志类的注解
@RequestMapping("/wechat") // 请求映射的注解
public class WeChatController {

	@PostMapping("/getUserInfo") // post请求的注解
	public Result user_login(@RequestParam("code") String code){

	// 配置请求参数
	Map<String, String> param = new HashMap<>();
	param.put("appid", WeChatConfig.WX_LOGIN_APPID);
	param.put("secret", WeChatConfig.WX_LOGIN_SECRET);
	param.put("js_code", code);
	param.put("grant_type", WeChatConfig.WX_LOGIN_GRANT_TYPE);
	// 发送请求
	String wxResult = HttpClientUtil.doGet(WeChatConfig.WX_LOGIN_URL, param);
	log.info(wxResult);
	
	JSONObject json = JSONObject.parseObject(wxResult);
	String open_id = json.get("openid").toString();
	String session_key = json.get("session_key").toString();
	
	// 根据返回的user实体类,判断用户是否是新用户,不是的话,更新最新登录时间,是的话,将用户信息存到数据库
	
	// 封装返回小程序
	Map<String, String> result = new HashMap<>();
	result.put("session_key", session_key);
	result.put("open_id", open_id);
	return new Result(1,"ok",result);	// 自己定义的返回类
    }

}

完成! 打开小程序开发端,点击授权登录,即可看见控制台返回的重要信息.

将小程序的 data中的canIUseOpenData:false 注释掉,就可以正常开发后续登录业务了

https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

 类似资料: