最近在做一个嵌在公众号里的H5项目,里面涉及到了微信支付,属于公众号支付,需要拿到用户的openid,涉及到了网页授权。
如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。
步骤
- 引导用户进入授权页面同意授权,获取code
- 通过code换取网页授权access_token(与基础支持中的access_token不同)
- 如果需要,开发者可以刷新网页授权access_token,避免过期
通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
详细介绍可以参考官网文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
实践步骤:
1、配置回调域名
在微信公众平台官网“开发–接口权限–网页服务–网页账号—网页授权获取用户基本信息”中配置回调域名(注:是一个字符串,不是URL,所以不要以http://等协议开头)
2、用户同意授权,获取code
引导用户打开如下页面:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
注:(1) 如果提示连接无法访问,请检查参数是否填写错误,是否拥有scope参数对应的权限作用域权限。
(2)在发起授权请求时,微信会对授权链接做正则匹配校验,如果链接的参数顺序不对,授权页面将无法访问。
参数说明:
redirect_uri:是授权之后需要跳转的页面(注:需要进行urlEncode处理)
这个网站可以进行urlEncode编码:http://tool.chinaz.com/Tools/urlencode.aspx
输入需要访问的地址,点UrlEncode编码就可以了。
scope:应用作用域有两种,小编只需要拿到openid就可以了,所以采用的snsapi_base
用户授权之后,页面跳转至 redirect_uri/?code=CODE&state=STATE
code是获取access_token的票据,每次用户授权获取的code不一样,code只能使用一次,5分钟未被使用将自动过期。
错误返回说明:
小编的项目业务:在用户登录成功跳转主页时获取code。到主页的页面地址上会有code和state的参数,在主页上截取到code参数传到后端,获取openid。
var searchStr = location.search;
var searchArr = searchStr.split("&");
var code = searchArr[0].replace("?code=", ""); //string
$http.get(urlpath + '/weChat/saveOpenid.do', {
params: {
code: code
}
}).success(function(response) {
});
3、后端saveOpenid方法获取openid。
Controller:
@RequestMapping("/saveOpenid")
public String saveOpenid(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 用户同意授权,获得的code
String code = request.getParameter("code");
String username=request.getParameter("phoneNum");
String appid = ""; //公众号appid
String appsecret = "";//公众号密钥
// 获取access_token和openid
String apiurl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + appsecret
+ "&code=" + code + "&grant_type=authorization_code";
JSONObject demoJson = HttpUtil.doGet(apiurl);
String access_token = demoJson.getString("access_token");
String openid = demoJson.getString("openid");
System.out.println("用户openid====" + openid);
}
工具类:HttpUtill
public class HttpUtil {
public static JSONObject doGet(String url)
{
JSONObject demoJson =new JSONObject();
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
http.setRequestMethod("GET"); // 必须是get方式请求
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
http.connect();
InputStream is = http.getInputStream();
int size = is.available();
byte[] jsonBytes = new byte[size];
is.read(jsonBytes);
String message = new String(jsonBytes, "UTF-8");
demoJson = JSONObject.fromObject(message);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return demoJson;
}
}
总结
学习是一个过程,实践需要一个过程!