Java微信公众平台网页授权获取用户基本信息(h5)(清风竹语)
1.提供一下相关微信开发文档:
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
2.使用场景:
微信网页开发
个人使用:当一个用户,无论是谁,通过扫码,或其他方式,进入该网页时,获取用户信息,并保存。在后台页面展示用户信息(没有登录,所以要依靠微信开发文档的帮助)。
所需数据格式:
{
- "openid":"oKDaK558PmMeGHg*************",
- "nickname":"∠※集",
- "sex":0,
- "language":"zh_CN",
- "city":"和平",
- "province":"天津",
- "country":"中国",
- "headimgurl":"https://thirdwx.qlogo.cn/mmopen/vi_32/DUxiaOqVGDQ2mukia08icYOgfP9Kal8KlzX2fYohibXqdUEKx9Zroxr6LISicxRD0jxkCJeyejiaH57JibSia51cNK1Y8Q/132",
- "privilege":[]
}
效果:用户通过微信进入页面后,首先会进入微信授权页面,用户同意后,会进入你设置好的页面,因为项目是vue写的,所以在页面加载后我就会在onLoad中调用,如果没用vue可以用Jquery(具体效果网上有图片,就不再这边复制粘贴了)。
2.流程:
1.首先申请一个微信测试账号(重)
1.地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
2.申请成功后 得到:applD和apseret 可以放在常用工具类中,也可以放入数据库中
3.配置JS接口安全域名:如果是本机测试的时候,直接填写本机IP即可
4.下方有一个测试号二维码,用你测试的微信,扫一下,注册即可。(不扫的话是访问不了的)
5.网页账号修改(重):最坑爹的东西没有之一。网上百度了很多,基本都是,填写项目域名即可。微信在用户授权之后,来访问该域名下的页面。比如www.baidu.cn下所有页面,但是在开发中,我们通常是本机测试,所以我测试了:localhost,127.0.0.1, 192.167.*.*等,甚至通过管理员权限修改了,本机域名。但是!都失败了!百度了那么多次,就他喵每一个人提出加端口号的(连微信文档上也是如此。。。),结果就是,如果是本机测试,记得域名后面加+端口号。。。,格式以127.0.0.1:8080的方式即可,但是要记得要是以此路径访问。
2.前端代码
1:获取code,在method{}下定义
getCode() { // 非静默授权,第一次有弹框
this.code = ''
var local = window.location.href // 获取页面url
console.log(local)
encodeURIComponent(local);
this.code = this.getUrlCode().code // 截取code
//var appid = 'wx51f761034f******'
var appid ='wxb318bb637a76a9e3'
if (this.code == null || this.code === '') { // 如果没有code,则去请求
//微信官方文档接口
window.location.href =
`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent(local)}&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect`
} else {
//上下全部代码,全部是用来获取用户code信息
//你自己的业务逻辑:我这边是调用一个getAuth方法,并将code传给后台
this.getAuth(this.code);
}
console.log(this.code)
},
getUrlCode() { // 截取url中的code方法
var url = location.search
this.winUrl = url
var theRequest = new Object()
if (url.indexOf("?") != -1) {
var str = url.substr(1)
var strs = str.split("&")
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = (strs[i].split("=")[1])
}
}
return theRequest
},
2.向后端请求(同样定义在method{}中)
//这边没有固定要求,只要能将code传入后台即可
getAuth(code) {
console.log(code);
const instance = new request();
return instance.get({
url: "/get_auth_access_token",
contentType: 'json',
data: {
code: code
},
xhrFields: {
withCredentials: true // 这里设置了withCredentials
}
});
},
3,后端代码(两个工具类,一个方法)
1.发送get,post请求的工具类
package co.yixiang.modules.shop.config;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
/**
* @author 逐月而行
* @version 1.0
* @date 2021/3/15 18:17
**/
public class HttpUtil {
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString=null;
if(null!=param){
urlNameString= url + "?" + param;
}else {
urlNameString = url;
}
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
public static void main(String[] args) {
JSONObject js = new JSONObject();
js.put("expire_seconds", 604800);
js.put("action_name", "QR_SCENE");
JSONObject j1 = new JSONObject();
j1.put("scene_id", 111111);
JSONObject j2 = new JSONObject();
j2.put("scene", j1);
js.put("action_info", j2);
String s = HttpUtil.sendPost("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=uG17gXKUrhrAgw7wAfiUQolnlGylW_5sc8BqKNtNTmmSEjbsNpgEz-6vq6G_U-EEUyU-1_QJ1lAWcLyx9PvvGWRX9F3iq4CiFa0_nMcxseeJ1vqpjxjCK-c78kuwhrTxFEUaAJAIHX", js.toString());
System.out.println(s);
}
}
2.设置常用参数的工具类
package co.yixiang.modules.shop.config;
/**
* @author 逐月而行
* @version 1.0
* @date 2021/3/15 18:08
**/
public class WxConstant {
//服务号
//APPID
public static final String SERVICE_APPID = "wxb318bb6********";
//APPSECRET
public static final String SERVICE_APPSECRET = "2a63db6075b81c*************";
}
3,最后方法
@GetMapping(value = "/get_auth_access_token")
public void getAuthAccessToken(@RequestParam("code") String code) {
//用户 openId
String openId = null;
//用户 accessToken
String accessToken = null;
try {
//获取Token
String urlToken = "https://api.weixin.qq.com/sns/oauth2/access_token";
String accessTokenObj = HttpUtil.sendGet(urlToken, "appid=" + WxConstant.SERVICE_APPID + "&secret="
+ WxConstant.SERVICE_APPSECRET + "&code=" + code + "&grant_type=authorization_code");
net.sf.json.JSONObject jsonToken = net.sf.json.JSONObject.fromObject(accessTokenObj);
if (StringUtils.isNotBlank(String.valueOf(jsonToken))) {
openId = jsonToken.getString("openid");
accessToken = jsonToken.getString("access_token");
//打印信息
System.out.println("openId" + openId + "accessToken" + accessToken);
}
} catch (Exception e) {
System.out.println(e);
}
try {
String urlInfo = "https://api.weixin.qq.com/sns/userinfo";
String infoObj = HttpUtil.sendGet(urlInfo, "access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN");
//这是一种JSON接解析方式:选择其中一种即可
net.sf.json.JSONObject jsonUserInfo = net.sf.json.JSONObject.fromObject(infoObj);
//这是另一个JSON解析方式:选择其中一种即可
JSONObject jsonUserInfo = JSONObject.parseObject(infoObj);
try {
//第一种取值方式
if (StringUtils.isNotBlank(String.valueOf(jsonUserInfo))) {
//一下是个人业务需求,请随意
String nickName = jsonUserInfo.getString("nickname");//获取用户名称
String headImgUrl = jsonUserInfo.getString("headimgurl");//获取用户头像(还有更多数据,根据需求进行使用)
YxUser yxUser = new YxUser();
yxUser.setAvatar(headImgUrl);
yxUser.setNickname(nickName);
yxUser.setUserType("0");
yxUser.setMark(openId);
yxUserService.save(yxUser);
}
//第二种取值方式优先与上面方法,可以有效避免null现象
if (StringUtils.isNotBlank(String.valueOf(jsonUserInfo))) {
YxUser yxUser = new YxUser();
yxUser.setNickname(jsonUserInfo.getString("nickname"));
yxUser.setAvatar(jsonUserInfo.getString("headimgurl"));
yxUser.setUserType("0");
yxUserService.save(yxUser);
}
} catch (Exception e) {
System.out.println(e);
}
} catch (Exception e) {
System.out.println(e);
}
}