写在前面
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 为:
1
| 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:
1 2 3 4 5 6
| App({ globalData: { userInfo: null } })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <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>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| .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; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| const app = getApp()
Page({ data: { userInfo: {}, usernoneSrc: "/images/user.png", hasUserInfo: false, canIUse: wx.canIUse('button.open-type.getUserInfo') }, 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) { app.userInfoReadyCallback = res => { this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } } else { 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| 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) { String getOpenIdUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId +"&secret=" + appSecret + "&js_code=" + code +"&grant_type=authorization_code"; System.out.println(getOpenIdUrl); HttpClient httpClient = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(getOpenIdUrl); ResponseHandler<String> responseHandler = new BasicResponseHandler(); String responseBody = httpClient.execute(httpGet,responseHandler); System.out.println("=========================获取token==================="); System.out.println(responseBody); JSONObject jsonObject = JSONObject.fromObject(responseBody); System.out.println(jsonObject.toString()); } 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 一万遍!因为比较长,很容易拼错。