场景:在手机端用微信回答问卷时,客户想要通过微信获取用户信息
使用:SpringBoot、有域名的服务器(https://damionew.top)、微信公众平台测试号(带链接)、文档
测试号信息appID 和 appsecret 是平台自动生成的
接口配置信息暂时无需填写
域名不要带https等
测试号二维码用于添加测试账号,只有列表中的用户才能使用,否则将提示无权限
任务目标
修改处填写域名,注意不要带https!
项目结构
pom文件,主要是HTTPClient 和 Tomcat
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.0.3.RELEASE
com.test
weChatAuth
0.0.1-SNAPSHOT
weChatAuth
war
微信授权
1.8
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
org.apache.httpcomponents
httpclient
org.springframework.boot
spring-boot-starter-tomcat
provided
org.apache.tomcat.embed
tomcat-embed-jasper
provided
com.alibaba
fastjson
1.2.47
org.springframework.boot
spring-boot-devtools
provided
true
log4j
log4j
1.2.17
wx
org.springframework.boot
spring-boot-maven-plugin
src/main/java
**/*.dat
false
src/main/resources
启动类如下,因为需要部署到带域名的服务器Tomcat上,所以继承了SpringBootServletInitializer 并重写configure
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class WeChatAuthApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(WeChatAuthApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WeChatAuthApplication.class);
}
}
项目配置,主要是Log4j和项目名(因为需要部署到外部服务器的Tomcat上)
server.servlet.context-path=/wx
## LOG4J配置
log4j.rootCategory=DEBUG,stdout
## 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
logging.level.com.guide.springboot.server.mapper=debug
请求工具类,返回的是JSONObject,使用的是fastjson的jar包
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
/**
* 微信处理工具类
* @author yinyunqi
*
*/
@Service
public class WeChatUtil {
private static final Logger log = LoggerFactory.getLogger(WeChatUtil.class);
public static JSONObject weChatTest(String url) {
CloseableHttpClient httpCilent = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
String result = "";
JSONObject jsonObject = new JSONObject();
try {
HttpResponse httpResponse = httpCilent.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
result = EntityUtils.toString(httpResponse.getEntity());//获得返回的结果
log.info(result);
jsonObject = JSONObject.parseObject(result);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonObject;
}
}
页面
Insert title here
点击获取权限
请求处理类,代码中大部分都已注释
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.fastjson.JSONObject;
/**
* 处理微信请求
* @author yinyunqi
*
*/
@Controller
public class WeChatController {
private static final Logger log = LoggerFactory.getLogger(WeChatController.class);
// 测试号平台 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
// 公众号的唯一标识【必需】
public static final String APPID = "wx3cc7cac0b41e9111";
// 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理【必需】
public static final String REDIRECT_URI = "https://damionew.top/wx/weChat/callBack";
// 返回类型,请填写code【必需】
public static final String RESPONSE_TYPE = "code";
// 应用授权作用域【必需】
// snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)
// snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
public static final String SCOPE = "snsapi_userinfo";
// 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节【非必需】
public static final String STATE = "123";
// 无论直接打开还是做页面302重定向时候,必须带此参数【必需】
public static final String wechat_redirect = "";
public static final String APPSECRET = "b51067db03de9fa9d785e99db70b937e";
/**
* 初始页面
* @return
*/
@RequestMapping("/weChat")
public String weChatTest() {
log.info("weChat");
return "weChat";
}
/**
* 点击页面超链请求此处
* @param req
* @param res
*/
@ResponseBody
@RequestMapping("/weChat/auth")
public void weChatAuth(HttpServletRequest req,HttpServletResponse res) {
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+APPID
+ "&redirect_uri="+REDIRECT_URI
+ "&response_type="+RESPONSE_TYPE
+ "&scope="+SCOPE
+ "&state="+STATE
+ "#wechat_redirect";
log.info("url"+url);
try {
res.sendRedirect(url);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 上方 REDIRECT_URI 变量中带有的回调请求,即用户点击确定授权后所做的操作
* @param req
* @param res
*/
@ResponseBody
@RequestMapping("weChat/callBack")
public void weChatCallBack(HttpServletRequest req,HttpServletResponse res){
String code = req.getParameter("code");
log.info("code为:"+code);
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+APPID
+ "&secret="+APPSECRET
+ "&code="+code
+ "&grant_type=authorization_code";
JSONObject jsonObject = WeChatUtil.weChatTest(url);
String openId = jsonObject.getString("openid");
String access_token = jsonObject.getString("access_token");
log.info("openid为"+openId);
// 拉取用户信息
String url2 = "https://api.weixin.qq.com/sns/userinfo?access_token="+access_token
+ "&openid="+openId
+ "&lang=zh_CN";
JSONObject userInfo = WeChatUtil.weChatTest(url2);
log.info("唯一标识为:" + userInfo.getString("openid"));
log.info("昵称为:" + userInfo.getString("nickname"));
log.info("性别为:" + userInfo.getString("sex"));
log.info("省为:" + userInfo.getString("province"));
log.info("市为:" + userInfo.getString("city"));
log.info("头像地址为:" + userInfo.getString("headimgurl"));
}
}
返回结果大致如下
这些都是通过服务器查看的打印日志信息,但最后发现,只能通过这种方式获取到openid,但可能并不符合客户预期
比如:绑定手机号码、微信号
但这也是微信为安全考虑,否则用户随便访问几个公众号,微信号手机号全暴露了,用户就可能会陷入无休止的被骚扰中
另外项目地址 GItHub