OpenID是用户在某一个公众号的唯一标识,用户不同公众号的的OpenID是不一样的。在开发的时候,我们有时需要获取用户的OpenID。本文将介绍以下内容:“用户页面授权HTML代码”、“调用服务器后端接口的js代码”、“用户静默授权后端接口”、“微信服务器回调我们的服务器接口”、“获取微信服务器返回的信息”。
1、用户页面授权HTML代码。
设计一个用户点击授权的前端页面:
<div id="loginMain">
<div id="loginInfomation" class="layui-form">
<h2>欢迎登录博销宝管理后台</h2>
<div class="layui-form-item">
<label class="layui-form-label"><strong class="requiredField">*</strong>公司编号:</label>
<div class="layui-input-block">
<input type="text" class="layui-input" name="${Staff.FIELD_NAME_companySN}" value="" lay-verify="required|checkCompanySN" placeholder="请输入公司编号" />
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><strong class="requiredField">*</strong>手机号码:</label>
<div class="layui-input-block">
<input type="text" class="layui-input" name="${Staff.FIELD_NAME_phone}" value="" lay-verify="required|checkPhone" maxlength="11" placeholder="请输入手机号码" />
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label"><strong class="requiredField">*</strong>密码:</label>
<div class="layui-input-block">
<input type="password" class="layui-input" name="${Staff.FIELD_NAME_salt}" value="" lay-verify="required|checkPassword" placeholder="请输入密码" />
</div>
</div>
<input type="hidden" value="${identify}" name="identify">
<input type="hidden" value="${ID}" name="ID">
<button class="layui-btn layui-btn-lg layui-btn-normal" lay-submit lay-filter="wxLogin">登录</button>
</div>
</div>
2、调用服务器后端接口的js代码。
//登录系统
form.on("submit(wxLogin)", function(data){
var indexLoading = layer.load(1);
var info = data.field;
$.ajax({
url: wxLogin_url,
type: 'get',
async: true,
dataType: "json",
data: info,
success: function succFunction(data) {
console.log(data);
layer.close(indexLoading);
if (data) {
if (data.ERROR != "EC_NoError") {
if (data.msg) {
layer.msg("<span style='font-size: 0.2rem;'>" + data.msg + "</span>");
} else {
layer.msg("<span style='font-size: 0.2rem;'>登录失败</span>");
}
} else {
switch (info.identify) {
case "purchasingOrder":
window.location.href = "../wx/purchasingOrderApproval.bx?ID=" + info.ID;
break;
case "unSalableCommodity":
window.location.href = "../wx/unsalableCommodity.bx";
break;
default:
console.log("未定义的标识符");
break;
}
}
} else {
layer.msg("<span style='font-size: 0.2rem;'>登录失败</span>");
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
layer.close(indexLoading);
layer.msg(XMLHttpRequest.status + ":" + XMLHttpRequest.statusText);
}
});
})
3、用户静默授权后端接口。
用户授权后,我们才能请求微信服务器获取用户信息。根据访问code的地址GET_CODE_URL,公众号账号appid和我们设置的回调接口callback_url生成url并访问微信服务器:
/** 用户请求页面(snsapi_userinfo页面授权) */
@RequestMapping(value = "/wxLogin") // ...
public void toGetAuthentication(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (!canCallCurrentAction(request.getSession(), BaseAction.EnumUserScope.ANYONE.getIndex())) {
logger.debug("无权访问本Action");
return;
}
logger.info("用户访问服务器!!!网页授权!!!");
// 检查Cookie值是否存在
// checkCookie(request, response);// ...可能在这个函数里面已经跳转,下面的代码不需要再跳转
String backUrl = callback_url;
String url = String.format(GET_CODE_URL, PUBLIC_ACCOUNT_APPID, URLEncoder.encode(backUrl, "UTF-8"), "snsapi_userinfo");// ...
// 页面重定向
response.sendRedirect(url);
}
4、微信服务器回调我们的服务器接口。
callBack接口是我们在用户授权的时候指定的回调接口:
/** 静默授权后,微信会回调本ACTION,获取用户OpenId 参考微信官方文档:XXXXXXX */
@RequestMapping(value = "/callBack")
public String getOpenId(HttpServletRequest request, HttpServletResponse response, ModelMap mm) throws ClientProtocolException, IOException, ServletException {
if (!canCallCurrentAction(request.getSession(), BaseAction.EnumUserScope.ANYONE.getIndex())) {
logger.debug("无权访问本Action");
return null;
}
……
获取微信返回的code,用code获取openid:
logger.info("callBack===接受到微信服务器发来的请求!!!");
String code = request.getParameter(BaseWxModel.WX_CODE);// 微信会返回code值,用code获取openid
根据获取用户openID的地址GET_OPENID_URL,公众号账号PUBLIC_ACCOUNT_APPID,公众号密码PUBLIC_ACCOUNT_SECRET和code拼接请求URL:
// 1.拼接URL
String url = String.format(GET_OPENID_URL, PUBLIC_ACCOUNT_APPID, PUBLIC_ACCOUNT_SECRET, code); // ...
向微信端发送请求,并返回JSON数据:
JSONObject jsonObject = WxUtils.getDataFromWxServer(url);
/** 通用函数。 向微信服务器发送Get请求,返回JSON数据。 */
public static JSONObject getDataFromWxServer(String url) {
HttpClient httpClient = HttpClientBuilder.create().build();
try {
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);// 接收client执行的结果
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity, "UTF-8");
return JSONObject.fromObject(result);
} else {
logger.error("向微信服务器发送Get请求发生错误!");
return null;
}
} catch (Exception e) {
logger.error("向微信服务器发送Get请求发生错误:" + e.getMessage());
return null;
}
}
5、获取微信服务器返回的信息。
判断返回的错误码信息:
if (jsonObject.get(BaseWxModel.WX_ERRMSG) != null) {
request.setAttribute("msg", "授权失败!!!请重新登录!");
response.sendRedirect("/WEB-INF/wx/wx_loginFinished.jsp");
}
获取微信端返回的openID数据:
String openid = jsonObject.getString(WxUser.field.getFIELD_NAME_openid()); // 用户唯一标识
String token = jsonObject.getString(WxAccessToken.field.getFIELD_NAME_accessToken()); // 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
String expires_in = request.getParameter(WxAccessToken.field.getFIELD_NAME_accessToken()); // access_token接口调用凭证超时时间,单位(秒)
String refresh_token = request.getParameter(BaseWxModel.WX_REFRESH_TOKEN); // 用户刷新access_token