微信小程序通過Java後臺獲取openid

寫在前面

Client: 微信小程序

Server: Java Servlet running on local Tomcat 9.0

Tools: 微信開發者工具 && Eclipse

獲取思路

參考試水微信小程序與Java後臺通信一文,我們可以快速建立起小程序與 Java 後臺之間的通信。而獲取 openid 之前,我們首先要知道微信小程序官方如何定義 openid 的工作機制。參考微信小程序公衆平臺的開發文檔:小程序登錄,可以得知 openid 的工作機制主要爲下圖所示:

由此可以得知小程序若想在後臺獲取到 openid 就必須在前端發送一個臨時生成的 code 到 Java 後臺,然後 Java 後臺使用 code 向微信相關 API 請求並獲得 session_key 以及 openid。請求的 API 爲:

https://api.weixin.qq.com/sns/jscode2session?appid=xxx&secret=xxx&js_code=xxx&grant_type=authorization_code

其中 appid 和 secret 祕鑰需要在開發者平臺的開發設置中獲取,且 secret 祕鑰不會明文保存,生成後記得保存下來,否則如果忘記需要重新生成。js_code 則是小程序傳回的臨時 code。

小程序端

小程序端製作一個簡單的測試界面,並在 js 中向後臺發送生成的 code:

//app.js
App({
  globalData: {
    userInfo: null
  }
})
<!--index.wxml-->
<view>
  <view class="userinfo">
    <block wx:if="{{!hasUserInfo && canIUse}}">
      <image class="userinfo-avatar" src="{{usernoneSrc}}" mode="cover"></image>
      <button open-type="getUserInfo" bindgetuserinfo="getUserInfo" style='margin-bottom:50rpx' bindtap="login"> 點擊授權 </button>
    </block>
    <block wx:else>
      <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>
  </view>
  <view class="vipText">
    <block wx:if="{{vipFlag}}">
      <text style='color:orange;border:1px solid orange;border-radius:25%;'>vip</text>
    </block>
    <block wx:else>
      <text style='color:#eee;border:1px solid #eee;border-radius: 25%;'>vip</text>
    </block>
  </view>
</view>
.userinfo {
  display: flex;
  flex-direction: column;
  align-items: center;
  border-bottom: 2px solid #eee;
}

.userinfo-avatar {
  width: 200rpx;
  height: 200rpx;
  margin: 50rpx;
  border-radius: 50%;
  border: 1px solid #eee;
}

.userinfo-nickname {
  color: #aaa;
  font-size: 60rpx;
  margin-bottom: 50rpx;
}

.vipText {
  width: 100%;
  text-align: center;
  margin-top: 50rpx;
}
const app = getApp()

Page({
  data: {
    userInfo: {},
    usernoneSrc: "/images/user.png",
    //vipFlag: true,
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },
  //登錄獲取code
  login: function () {
    wx.login({
      success: function (res) {
        //發送請求
        wx.request({
          url: 'http://localhost:8080/smallAPP/ConnectTest', //接口地址
          data: { code: res.code },
          header: {
            'content-type': 'application/x-www-form-urlencoded'
          },
          success: function (res) {
            console.log(res.data);
          },
          fail: function (res) {
            console.log("Fail to connect...");
          }
        })
      }
    })
  },
  onLoad: function () {
    if (app.globalData.userInfo) {
      this.setData({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true
      })
    } else if (this.data.canIUse) {
      // 由於 getUserInfo 是網絡請求,可能會在 Page.onLoad 之後才返回
      // 所以此處加入 callback 以防止這種情況
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    } else {
      // 在沒有 open-type=getUserInfo 版本的兼容處理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        }
      })
    }
  },
  getUserInfo: function (e) {
    console.log(e)
    app.globalData.userInfo = e.detail.userInfo
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
  }
})

界面如下:

Server

lib

除了試水微信小程序與Java後臺通信一文中的 json 相關包,我們還需要導入一個用於進行 Http 請求的 Apache 的工具:HttpClient。該工具本來位於 Apache 的 Commons 項目中,但是後來置於 Apache 的 HttpComponents 項目中了,具體說明詳見 Apache Commons 以及 Jakarta Commons HttpClient

Download HttpClient

Servlet

package com.smallAPP.common;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import net.sf.json.JSONObject;

@WebServlet("/ConnectTest")
public class ConnectTest extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public ConnectTest() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {//設置請求編碼
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        
        String code = request.getParameter("code");
        System.out.println(code);
        
        String appSecret = "對應secret祕鑰";
        String appId = "對應APPID";
        
        if (code != null) {
            //獲取openid和access_token的連接
            String getOpenIdUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId +"&secret=" + appSecret + "&js_code=" + code +"&grant_type=authorization_code";
            System.out.println(getOpenIdUrl);
            //獲取返回的code
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(getOpenIdUrl);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            //向微信發送請求並獲取response
            String responseBody = httpClient.execute(httpGet,responseHandler);
            System.out.println("=========================獲取token===================");
            System.out.println(responseBody);
            JSONObject jsonObject = JSONObject.fromObject(responseBody);
            System.out.println(jsonObject.toString());
        }
        
        //轉成json數據
        Map<String, Object> result = new HashMap<String, Object>();
        result.put("data", code);
        result.put("msg", "後臺已收到");
        JSONObject object = JSONObject.fromObject(result);
        PrintWriter out = response.getWriter();
		out.print(object.toString());
		out.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}
}

測試

在小程序界面點擊綁定了發送 code 代碼的按鈕後,小程序端獲取授權以及用戶頭像等基本信息,如下圖:

此時觀察後臺的結果,看是否獲取到 openid:

如上圖所示已經成功獲取了 openid。

一些坑

  • HttpClient 這個工具包已經換位置了。
  • 如果請求返回有錯誤,請檢查請求的 API 一萬遍!因爲比較長,很容易拼錯。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章