文档链接:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
首先需要到微信公众号进行一些设置,这里以测试公众号为例进行说明。
首先到如下链接申请一个测试公众号:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login,直接用微信扫一下码即可注册成功,简单快捷!
申请好测试公众号之后,登录到后台进行管理,如下所示:
注意如下参数(参数列表):
1.appID:微信公众号应用id
2.appsecret:微信公众号应用秘钥
3.URL:进行接入开发的url
4.token:令牌,类似于密码
5.JS安全域名:一种安全设置,调用微信JS-SDK的时候,域名必须符合这里的设置
6.授权回调域名:授权步骤中,微信需要回调你的接口,这个接口的域名就是在这里设置的。
以上参数中,3到6都是需要各位亲自己去设置的哦!
---------------------------------------------------- 分隔符 ----------------------------------------------------
好了,进行这些设置后,让我们进入开发吧,但是开发之前,需要进行接入操作,也就是说,你得让微信公众号服务器去验证你的服务器所在的url地址和域名等信息。(经过实测,这个接入操作是可以省略的)
首先开发一个http接口(以java代码为例,后面都是用java来说明的):
/**
* 验证开发者,确认请求来自微信服务器
*
* @param signature
* @param timestamp
* @param nonce
* @param echostr
* @param response
* @throws IOException
*/
@RequestMapping(value="/access", method=RequestMethod.GET)
public void wxAccess(String signature, String timestamp, String nonce, String echostr,
HttpServletResponse response) throws IOException {
try {
response.setHeader("Content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
if (signature == null) {
out.write("参数错误!");
}
boolean result = SignUtil.validSign(signature, WeixinConstant.TOKEN, timestamp, nonce); //WeixinConstant.TOKEN即参数列表中的"4.token:令牌,类似于密码"
if (result) {
out.write(echostr);
System.out.println("验证完成");
} else {
out.write("验证失败!");
}
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("完成操作!");
}
public class SignUtil {
public static boolean validSign(String signature, String tocken, String timestamp, String nonce) {
String[] paramArr = new String[] { tocken, timestamp, nonce };
Arrays.sort(paramArr);
StringBuilder sb = new StringBuilder(paramArr[0]);
sb.append(paramArr[1]).append(paramArr[2]);
String ciphertext = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(sb.toString().getBytes());
ciphertext = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return ciphertext != null ? ciphertext.equals(signature.toUpperCase()) : false;
}
private static String byteToStr(byte[] byteArray) {
String rst = "";
for (int i = 0; i < byteArray.length; i++) {
rst += byteToHex(byteArray[i]);
}
return rst;
}
private static String byteToHex(byte b) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(b >>> 4) & 0X0F];
tempArr[1] = Digit[b & 0X0F];
String s = new String(tempArr);
return s;
}
}
注意,这个接口必须支持get方式的请求,因为微信发出接入请求是通过get方式进行的。还有就是这个接口的url要对应上面参数列表中的"3.URL:进行接入开发的url"
好了,接入完毕之后,我们开始写授权的接口。
/**
* 用户授权
* @param request
* @param response
*/
@RequestMapping("/auth")
public String auth(HttpServletRequest request, HttpServletResponse response) {
try {
String redirectURL = "";
redirectURL = Constant.ENTRANCE_URL; //Constant.ENTRANCE_URL即下文中的回调接口
String pageURL = request.getParameter("pageURL"); //pageURL即用户需要去的页面url,在授权完毕后会重定向到该页面
redirectURL += "?pageURL=" + pageURL;
/*String params = request.getQueryString();
if(StringUtils.isNotBlank(params)) {
redirectURL += "?" + params;
}*/
String redirectURL_encode = java.net.URLEncoder.encode(redirectURL, WeixinConstant.CHARSET);
String authURL = WeixinConstant.CODE_AUTH_URL.replace("APPID", WeixinConstant.APPID)
.replace("REDIRECT_URI", redirectURL_encode)
.replace("SCOPE", WeixinConstant.SCOPE_BASE)
.replace("STATE", WeixinConstant.STATE);
//System.out.println(authURL);
return "redirect:" + authURL;
} catch (Exception e) {
log.error("授权失败", e);
}
return "redirect:" + Constant.INDEX_URL;
}
这里贴出WeixinConstant类的代码:
/**
* @author mawj
* @date 2017年6月21日 上午8:52:48
* 微信配置文件
*/
public class WeixinConstant {
private WeixinConstant() {
}
//微信号
public static final String WEIXINCODE;
//appID
public static final String APPID;
//appsecret
public static final String APPSECRET;
//token
public static final String TOKEN;
//charset
public static final String CHARSET;
//授权类型
public static final String SCOPE_BASE = "snsapi_base";
//授权STATE
public static final String STATE = "123";
//access_token的key
public static final String ACCESS_TOKEN = "access_token";
//jsapi_ticket的key
public static final String JSAPI_TICKET = "jsapi_ticket";
//授权URL,获取code
public static String CODE_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
//授权URL,获取access_token和openid
public static String TOKEN_AUTH_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
//获取access_token
public static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
//获取jsapi_ticket
public static String JSAPI_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
//发送模板消息url
public static String SEND_TEMPLATE_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
//发送消息通路url
public static String SEND_MSG_PATH_URL = "https://api.weixin.qq.com/cityservice/sendmsgdata?access_token=ACCESS_TOKEN";
//创建公众号菜单
public static String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
static {
WEIXINCODE = WeixinPropertyManager.getProperty("weixincode");
APPID = WeixinPropertyManager.getProperty("appID");
APPSECRET = WeixinPropertyManager.getProperty("appsecret");
TOKEN = WeixinPropertyManager.getProperty("token");
CHARSET = WeixinPropertyManager.getProperty("charset");
}
}
接下来要开发回调接口,在微信公众号服务器执行完授权步骤之后,会重定向到该地址:
/**
* 回调地址
* @param request
* @param response
*/
@RequestMapping("/entrance")
public String entrance(HttpServletRequest request, HttpServletResponse response) {
String pageURL = "";
try {
String code = request.getParameter("code");
pageURL = request.getParameter("pageURL");
String json_result = "";
if(StringUtils.isNotBlank(code)) {
String authURL = WeixinConstant.TOKEN_AUTH_URL.replace("APPID", WeixinConstant.APPID)
.replace("SECRET", WeixinConstant.APPSECRET)
.replace("CODE", code);
json_result = HttpUtil.doGet(authURL);
}
//System.out.println(">>>>>" + json_result);
if(StringUtils.isNotBlank(json_result)) {
JSONObject obj_result = JSONObject.fromObject(json_result);
String openid = obj_result.optString("openid");
System.out.println("用户授权成功:" + openid);
if(StringUtils.isNotBlank(openid)) {
request.getSession().setAttribute(WeixinConstant.SESSION_OPEN_ID, openid);
}
}
} catch (Exception e) {
log.error("授权出错", e);
}
if(pageURL == null || pageURL.equals("") || pageURL.equals("null") || pageURL.equals("NULL")) {
return "redirect:" + Constant.INDEX_URL;
}
return "redirect:" + pageURL;
}
其中,HttpUtil.doGet()的使用可以参考我这篇博文:https://blog.csdn.net/qq9808/article/details/78320816
在处理完授权的逻辑之后,就可以重定向到用户真正要去的那个页面了。
开发完毕后,授权入口格式如下所示:
http://ip:port/auth?pageURL=http://www.baidu.com