订阅号登录一: 简介
通过 微信公众平台----权限接口 可以得知 微信的订阅号是没有授权登录接口的,只有服务号才有该权限。
这点微信公众平台在多处反复强调
最终的事实是:微信订阅号是可以实现授权登录的!
二:具体实现步骤:
URL: 这里的地址我写的是我们HTML5项目的某个Controller或Servlet的地址,例如 http://www.example.com/weixin/checkSignature.do
注意这个CheckSignatureController中是要写代码的,代码的业务逻辑是要验证签名并返回echostr字段;还需要注意www.example.com 这个地址必须是外网地址(内网不行的), 因为当你配置完所有的基本信息时,当提交的时候,微信公众平台会回答你刚才填的URL地址即http://www.example.com/weixin/checkSignature.do, 如果你填内网的地址,那么这个URL调不到,如果签名验证不过去,这个基本配置就配置不成功。
当你写好这个CheckSignatureController后,还要将代码放到测试环境中去,以便微信公众平台可以回调你这个Controller
@Controller @RequestMapping(value="/weixin") public class CheckSignatureController extends BaseController { private static transient final Logger log = LoggerFactory.getLogger(CheckSignatureController.class); public static String WEIXIN_TOKEN = "Token"; @RequestMapping(value ="checkSignature.do", produces = "application/json; charset=utf-8") @ResponseBody public String checkSignature(HttpServletRequest request) { String echostr = request.getParameter("echostr"); // 随机字符串 if (isSignature(request)) { return echostr; } return null; } // 检查签名 public boolean isSignature(HttpServletRequest request) { String signature = request.getParameter("signature"); // 微信加密签名 String timestamp = request.getParameter("timestamp"); // 时间戳 String nonce = request.getParameter("nonce"); // 随机数 String[] arr = new String[] {timestamp, nonce, WEIXIN_TOKEN}; Arrays.sort(arr); String s = arr[0] + arr[1] + arr[2]; MessageDigest md; byte[] digest = null; try { md = MessageDigest.getInstance("SHA-1"); digest = md.digest(s.getBytes("utf-8")); } catch (Exception e) { e.printStackTrace(); } String sign = bytesToHexString(digest); return signature.equals(sign); } public static final String bytesToHexString(byte[] bArray) { StringBuffer sb = new StringBuffer(bArray.length); String sTemp; for (int i = 0; ibArray.length; i++) { sTemp = Integer.toHexString(0xFFif (sTemp.length()2) sb.append(0); sb.append(sTemp.toUpperCase()); } return sb.toString().toLowerCase(); } }
当你点击基本信息的【提交】按钮时,微信公众平台会向你项目发送http请求:
http://www.example.com/weixin/checkSignature.do?signature=d96625be6855baa013e6c66cb9155dd38ed8deb5 static String AppID = "微信开放平台的网站应用(不能是移动应用)https://open.weixin.qq.com (更不是公众平台切记)AppID"; static String AppSecret = "微信开放平台Secret"; static String State = "1"; @RequestMapping(value ="/oauth2.do", produces = "application/json; charset=utf-8") @ResponseBody public String mp(HttpServletRequest request) { // 1. 获取code ---------------------------------------------------- String CODE = request.getParameter("code"); String state = request.getParameter("state"); if (!State.equals(state)) { return null; } JsonMapper json = JsonMapper.nonDefaultMapper(); AccessTokenHelper accessTokenHelper = AccessTokenHelper.getInstance(); AccessToken accessToken = accessTokenHelper.getAccessToken(); if (accessToken != null) { Date expireEndDate = accessTokenHelper.getExpireInDate(); if (new Date().getTime() = expireEndDate.getTime() ) { // 2.accessToken过期了,需要重新获取 使用code换取access_token-------- accessToken = requestAccessToken(CODE, json); } } else { accessToken = requestAccessToken(CODE, json); } String accessTokenStr = accessToken.getAccess_token(); String openid = accessToken.getOpenid(); log.info("--accessToken: " + accessToken); // 3.使用access_token获取用户信息------------------------------- // https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKENString, Object paramMap = new HashMapString, Object(); String userinfoURL = "https://api.weixin.qq.com/sns/userinfo"; paramMap.clear(); paramMap.put("access_token", accessTokenStr); paramMap.put("openid", openid); String userinfoResponse = HttpClientUtil.doPostSSL(userinfoURL, paramMap); UserInfo userinfo = json.fromJson(userinfoResponse, UserInfo.class); log.info("--userinfo: " + userinfo); return CODE; } // https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID MapString, Object paramMap = new HashMapString, Object(); paramMap.put("appid", AppID); paramMap.put("secret", AppSecret); paramMap.put("code", code); paramMap.put("grant_type", "authorization_code"); String accessTokenResponse = HttpClientUtil.doPostSSL(accessTokenURL, paramMap); AccessToken accessToken = json.fromJson(accessTokenResponse, AccessToken.class); AccessTokenHelper accessTokenHelper = AccessTokenHelper.getInstance(); int expiresIn = accessToken.getExpires_in(); Date expireEndDate = DateUtil.addSeconds(new Date(), expiresIn); accessTokenHelper.setExpireInDate(expireEndDate); accessTokenHelper.setAccessToken(accessToken); return accessToken; } }
该代码用到json.fromJson()用于将json数据转为实体类,大家可以将该方法替换成自己的方法
HttpClientUtil.doPostSSL():是用于发送https请求的方法,大家可以将该方法替换成自己的方法
整篇文章一直在强调要AppID使用微信开放平台的网站应用AppID,
微信开放平台:登录:https://open.weixin.qq.com ---》 管理中心------》网站应用 如果你还没有网站应用那就必须创建一个网站应用,提交审核好像是要收费300元的
当Oauth2Controller开发后,放到测试环境中,此时要注意测试环境的服务器的JDK,不能使用OpenJDK,要使用Sun的SDK,否则在发送https请求会报错。
注意:有的评论说这篇博客帮助了他,有的说博客内容有误,我也不是很清楚,我只是把我在公司做的这个功能记录上来,上线也一直在用,具体博客内容有没有问题请大家自己判断,毕竟不是所有的博客都100%的对,本人水平有限
参考文章: http://www.cnblogs.com/txw1958/p/weixin71-oauth20.html