Skip to content

Instantly share code, notes, and snippets.

@Ericwyn
Created February 23, 2019 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Ericwyn/03eda7c3b8da0625c3eaad596345a39c to your computer and use it in GitHub Desktop.
Save Ericwyn/03eda7c3b8da0625c3eaad596345a39c to your computer and use it in GitHub Desktop.
微信登录获取 OpenId
package com.besfim.wxpay.controller;
import com.alibaba.fastjson.JSONObject;
import com.besfim.wxpay.utils.HttpUtils;
import com.besfim.wxpay.utils.SHA1;
import com.besfim.wxpay.utils.obj.ResJson;
import org.apache.http.HttpException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.http.HttpServletRequest;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
*
* 微信公众号开发,获取 openid 之类的
*
* 微信公众号鉴权如下
*
* - 访问某个 login 接口(服务器提供),这是个 URL_A
* - 该接口负责拼接出一个 wx 的 url,让用户跳转,这个 url 带有一个跳转的 URL_B
* - 用户跳转到 wx 的 url,这个 url 会在微信手机端提示用户鉴权,
* 用户允许之后,会跳转到 URL_B?code={CODE}
* - URL_B 是一个接口,负责接受 CODE 参数,然后将 CODE 参数带上 appid 和 secret 等
* 向微信官方服务器换取该用户的 OpenId,至此该用户完成登录
*
* Created by Ericwyn on 19-2-18.
*/
@Controller
public class WechatController {
// // 正式微信公众号 id 和 secret
private static final String appid="openid";
private static final String secret="secret";
// //正式部署时候的域名,关系到能够成功跳转微信获取 openid 的接口
private static final String runDomain = "https://wx.meetwhy.com";
// 一个中途转跳的 URL,用户在允许微信鉴权之后,跳转到 URL?code=CODE
private static final String URI_REDIRECT = "/user/wx/code";
private OkHttpClient httpClient = HttpUtils.getClient();
/**
* 通过这个地址转跳去微信官方地址,以获取微信登录的 code
* 并在之后跳转到正式登录接口
*
* @return
*/
@RequestMapping("/user/wx/login")
public String redirectToWechat(){
return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appid+"&redirect_uri="+ URLEncoder.encode(runDomain+ URI_REDIRECT)+"&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
}
/**
* 获取 Code 之后就访问这个地址
*
*
* @param request
* @return
* @throws HttpException
* @throws IOException
*/
@RequestMapping(value = URI_REDIRECT)
public String wexinRegister(HttpServletRequest request) throws IOException {
System.out.println("收到微信注册请求");
String openid ;
//用户微信登录获取openid
String code=(String) request.getParameter("code");
System.out.println(" code 是 "+code);
if(code==null){
return "redirect:ErrorPageInWechatLogin.html";
}
Request wxRequest = new Request.Builder()
.url(String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appid,secret,code))
.get()
.build();
Response response = httpClient.newCall(wxRequest).execute();
if (response.isSuccessful()){
String respText = response.body().string();
JSONObject json = JSONObject.parseObject(respText);
openid = json.getString("openid");
return ("redirect:"+runDomain+"/wx.html?openid="+ openid);
}else {
return ("redirect:"+runDomain+"/wx.html?openid=获取id失败");
}
}
// 获取jssdk 认证所需 appid,timestamp,noncestr,signature等信息,需要后端小伙伴配合
@RequestMapping(value = "/user/wx/jssdk",method = RequestMethod.POST)
@ResponseBody
public ResJson registerJsSdk(@RequestParam("url") String url){
JsApiRegistResJson json = getJsApiRegist(url);
if (json == null){
return ResJson.failJson(-1, "获取失败", null);
}
return ResJson.successJson("获取成功", json);
}
private class JsTicket {
String ticket;
Long createTime;
}
// 应该写在Server 里面的获取 Js ticket 的
// private HashMap<String, JsTicket> jsTicketMap = new HashMap<>();
// 获取 JsTicket,每个 url 对应的每个 ticket 有 7200s 的有效时间
// private Long lastGetTime=0L;
private String jsTicket = null;
private Long lastGetTime=0L;
private String accessToken = null;
public class JsApiRegistResJson {
private String appid;
private String timeStamp;
private String nonceStr;
private String signature;
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
}
public String getNonceStr() {
return nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSignature() {
return signature;
}
public void setSignature(String signature) {
this.signature = signature;
}
}
public JsApiRegistResJson getJsApiRegist(String url){
String jsTicket = getJsTicket();
if (jsTicket == null){
return null;
}
String timeStamp = (""+System.currentTimeMillis()).substring(0,10);
String nonceStr = System.currentTimeMillis()+"Test";
String signature = SHA1.encode(
"jsapi_ticket="+jsTicket+
"&noncestr="+nonceStr +
"&timestamp="+timeStamp +
"&url="+url
);
JsApiRegistResJson json = new JsApiRegistResJson();
json.appid = appid;
json.timeStamp = timeStamp;
json.nonceStr = nonceStr;
json.signature = signature;
return json;
}
// 获取 jsTicket(避免过时)
private String getJsTicket(){
if (jsTicket == null){
jsTicket = refreshJsTicket();
lastGetTime = System.currentTimeMillis();
}else {
if ((System.currentTimeMillis() - lastGetTime) > 1000 * 7200){
jsTicket = refreshJsTicket();
lastGetTime = System.currentTimeMillis();
}
}
return jsTicket;
}
// 刷新 JsTicket
private String refreshJsTicket(){
if (accessToken == null){
accessToken = getAccessToken();
}
Request request = new Request.Builder()
.get()
.url("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken+"&type=jsapi")
.build();
try {
Response response = httpClient.newCall(request).execute();
if (response.isSuccessful()) {
JSONObject json = JSONObject.parseObject(response.body().string());
String ticketTemp = json.getString("ticket");
if (ticketTemp != null){
System.out.println("刷新 jsTicket 成功" + ticketTemp);
return ticketTemp;
}else {
return null;
}
}else {
return null;
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// 获取 AccessToken
private String getAccessToken(){
Request request = new Request.Builder()
.get()
.url("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+secret)
.build();
try {
Response response = httpClient.newCall(request).execute();
if (response.isSuccessful()){
JSONObject json = JSONObject.parseObject(response.body().string());
String accessToken;
if ((accessToken = json.getString("access_token") )!= null){
System.out.println("获取 accessToken 成功" + accessToken);
return accessToken;
}else {
return null;
}
}else {
return null;
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment