1、服务接口配置
- 配置依赖
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
- 配置文件 weixin.properties
#验证服务器使用的token
weixin.token = test
#公众号信息
weixin.appid =
weixin.secret =
#获取接口凭证:普通access_token
weixin.tokenUrl = https://api.weixin.qq.com/cgi-bin/token
#获取接口凭证:授权 access_token
weixin.authTokenUrl = https://api.weixin.qq.com/sns/oauth2/access_token
#获取用户列表
weixin.userListUrl = https://api.weixin.qq.com/cgi-bin/user/get
#获取用户信息:根据 openid
weixin.userInfoDirectUrl = https://api.weixin.qq.com/cgi-bin/user/info
#获取用户信息:根据授权
weixin.userInfoAuthUrl = https://api.weixin.qq.com/sns/userinfo
#获取jsapi_ticket
weixin.ticketUrl = https://api.weixin.qq.com/cgi-bin/ticket/getticket
- 配置类 WeixinConfig
package com.vim.common.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "weixin")
@PropertySource("classpath:weixin.properties")
public class WeixinConfig {
//验证服务器使用的token
private String token;
//公众号信息
private String appid;
private String secret;
//获取接口凭证:普通 access_token
private String tokenUrl;
//获取接口凭证:授权 access_token
private String authTokenUrl;
//获取用户列表
private String userListUrl;
//获取用户信息:根据 openid
private String userInfoDirectUrl;
//获取用户信息:根据授权
private String userInfoAuthUrl;
//获取jsapi_ticket
private String ticketUrl;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getTokenUrl() {
return tokenUrl;
}
public void setTokenUrl(String tokenUrl) {
this.tokenUrl = tokenUrl;
}
public String getAuthTokenUrl() {
return authTokenUrl;
}
public void setAuthTokenUrl(String authTokenUrl) {
this.authTokenUrl = authTokenUrl;
}
public String getUserListUrl() {
return userListUrl;
}
public void setUserListUrl(String userListUrl) {
this.userListUrl = userListUrl;
}
public String getUserInfoDirectUrl() {
return userInfoDirectUrl;
}
public void setUserInfoDirectUrl(String userInfoDirectUrl) {
this.userInfoDirectUrl = userInfoDirectUrl;
}
public String getUserInfoAuthUrl() {
return userInfoAuthUrl;
}
public void setUserInfoAuthUrl(String userInfoAuthUrl) {
this.userInfoAuthUrl = userInfoAuthUrl;
}
public String getTicketUrl() {
return ticketUrl;
}
public void setTicketUrl(String ticketUrl) {
this.ticketUrl = ticketUrl;
}
}
- 配置工具类 HttpClientUtils
package com.vim.common.utils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public class HttpClientUtils {
/**
* 发送请求
* @param url 请求地址
* @param method 请求类型 GET\POST
* @param params 请求参数
*/
public static String send(String url, RequestMethod method, List<NameValuePair> params){
CloseableHttpClient client = HttpClientBuilder.create().build();
CloseableHttpResponse response = null;
try {
//请求信息
params = null == params ? new ArrayList<>() : params;
URI uri = new URIBuilder(url).setParameters(params).build();
HttpRequestBase request = null;
if(method.equals(RequestMethod.GET)){
request = new HttpGet(uri);
}else{
request = new HttpPost(uri);
}
//请求配置
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(5000)
.setConnectionRequestTimeout(5000)
.setSocketTimeout(5000)
.setRedirectsEnabled(true).build();
request.setConfig(config);
//发送请求
response = client.execute(request);
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}catch (Exception e){
e.printStackTrace();
}
return "";
}
public static void main(String[] args) {
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("loginName", "admin"));
params.add(new BasicNameValuePair("password", "123456"));
String result = HttpClientUtils.send("http://localhost:8080/api/api/user/login", RequestMethod.POST, params);
System.out.println(result);
}
}
- 配置工具类 WeixinUtils
package com.vim.common.utils;
import com.vim.common.properties.WeixinConfig;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@Component
public class WeixinUtils {
private static WeixinUtils weixinUtils;
@Autowired
private WeixinConfig config;
@PostConstruct
public void init() {
weixinUtils = this;
}
/**
* 签名校验
* @param signature
* @param timestamp
* @param nonce
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
List<String> params = new ArrayList<String>();
params.add(weixinUtils.config.getToken());
params.add(timestamp);
params.add(nonce);
// 1. 排序
Collections.sort(params, Comparator.comparing(String::toString));
// 2. 接成一个字符串进行sha1加密
String sha1Str = DigestUtils.sha1Hex(params.get(0) + params.get(1) + params.get(2));
return sha1Str.equals(signature);
}
}
- 配置服务器 ServerConfigController
package com.vim.modules.web.controller;
import com.vim.common.utils.WeixinUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
* 微信服务器接入
*/
@Controller
@RequestMapping(value = "/server")
public class ServerConfigController {
@RequestMapping(method = RequestMethod.GET)
public void get(HttpServletRequest request, HttpServletResponse response) {
try {
PrintWriter pw = response.getWriter();
//消息来源可靠性验证
String signature = request.getParameter("signature"); // 微信加密签名
String echostr = request.getParameter("echostr"); // 随机字符串
//将token、timestamp、nonce三个参数进行字典序排序
String timestamp = request.getParameter("timestamp"); // 时间戳
String nonce = request.getParameter("nonce"); // 随机数
if(WeixinUtils.checkSignature(signature, timestamp, nonce)){
pw.print(echostr);
}
}catch (Exception e){
e.printStackTrace();
}
}
@RequestMapping(method = RequestMethod.POST)
public void post(HttpServletRequest request, HttpServletResponse response){
}
}
- 配置启动类
package com.vim;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
@EnableConfigurationProperties
public class WeixinApplication {
public static void main(String[] args) {
SpringApplication.run(WeixinApplication.class, args);
}
}
2、获取 accessToken(普通接口调用凭证)
- 修改工具类,添加内容
/**
* 获取最新accessToken
*/
public static String latestAccessToken(){
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("grant_type", "client_credential"));
params.add(new BasicNameValuePair("appid", weixinUtils.config.getAppid()));
params.add(new BasicNameValuePair("secret", weixinUtils.config.getSecret()));
String result = HttpClientUtils.send(weixinUtils.config.getTokenUrl(), RequestMethod.GET, params);
JSONObject map = (JSONObject) JSON.parse(result);
return map.getString("access_token");
}
3、获取 accessToken(授权接口调用凭证)
/**
* 获取授权accessToken
* access_token:网页授权接口调用凭证
* expires_in: access_token接口调用凭证超时时间,单位(秒)
* refresh_token:用户刷新access_token
* openid:用户唯一标识
* scope:用户授权的作用域,使用逗号(,)分隔
*/
public static JSONObject authToken(String code){
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("appid", weixinUtils.config.getAppid()));
params.add(new BasicNameValuePair("secret", weixinUtils.config.getSecret()));
params.add(new BasicNameValuePair("code", code));
params.add(new BasicNameValuePair("grant_type", "authorization_code"));
String result = HttpClientUtils.send(weixinUtils.config.getAuthTokenUrl(), RequestMethod.GET, params);
return (JSONObject) JSON.parse(result);
}
4、获取用户列表(返回 openid 列表)
- 修改工具类,添加内容
/**
* 获取用户列表
* @param next_openid
*/
public static List<String> userList(String next_openid){
List<String> openidList = new ArrayList<>();
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("access_token", latestAccessToken()));
params.add(new BasicNameValuePair("next_openid", next_openid));
String result = HttpClientUtils.send(weixinUtils.config.getUserListUrl(), RequestMethod.GET, params);
JSONObject map = (JSONObject) JSON.parse(result);
Integer count = map.getInteger("count");
if(count > 0){
JSONArray array = map.getJSONObject("data").getJSONArray("openid");
openidList.addAll(array.toJavaList(String.class));
}
return openidList;
}
5、获取用户信息
- 修改工具类,添加内容
/**
* 获取用户信息
* @param url 根据openid直接拉取、根据授权拉取
* @param token 两种情况 token 不一样
* @param openid
*/
public static JSONObject userInfo(String url, String token, String openid){
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("access_token", token));
params.add(new BasicNameValuePair("openid", openid));
params.add(new BasicNameValuePair("lang", "zh_CN"));
String result = HttpClientUtils.send(url, RequestMethod.GET, params);
return (JSONObject) JSON.parse(result);
}
6、微信授权获取用户信息
- 微信回调配置
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxa6342ab93f0d18c0&redirect_uri=http%3A%2F%2Fwww.hxl2hzl.com%2Fweixin%2Fauthorize&response_type=code&scope=snsapi_userinfo&state=STATE001#wechat_redirect
- 控制器
package com.vim.modules.web.controller;
import com.alibaba.fastjson.JSONObject;
import com.vim.common.properties.WeixinConfig;
import com.vim.common.utils.WeixinUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class WeixinController {
@Autowired
private WeixinConfig config;
/**
* 授权
* @param code 授权code
* @param state 参数回调
*/
@RequestMapping(value = "/authorize")
@ResponseBody
public void authorize(@RequestParam(value = "code") String code, @RequestParam(value = "state", required = false) String state){
//1.回调 code 和 state
System.out.println("code="+code+", state="+state);
JSONObject authToken = WeixinUtils.authToken(code);
//2.获取 access_token 和 openid
System.out.println("access_token="+authToken.getString("access_token")+", openid="+authToken.getString("openid"));
//3.拉取用户信息
JSONObject userInfo = WeixinUtils.userInfo(config.getUserInfoAuthUrl(), authToken.getString("access_token"), authToken.getString("openid"));
System.out.println(userInfo.toJSONString());
}
}
7、获取 jsapi_ticket
- 修改工具类,添加内容
/**
* 获取 jsapi 签名
* @param pageUrl
* @return
*/
public static JSONObject ticketSignture(String pageUrl){
JSONObject result = new JSONObject();
//1.签名参数
String jsapi_ticket = ticket();
String noncestr = UUID.randomUUID().toString();
String timestamp = Long.toString(System.currentTimeMillis() / 1000);;
//签名排序
StringBuffer sb = new StringBuffer();
sb.append("noncestr=").append(noncestr).append("&");
sb.append("jsapi_ticket=").append(jsapi_ticket).append("&");
sb.append("timestamp=").append(timestamp).append("&");
sb.append("url=").append(pageUrl);
String signature = DigestUtils.sha1Hex(sb.toString());
System.out.println(sb.toString());
System.out.println("signature="+signature);
//3.返回签名
result.put("appid", weixinUtils.config.getAppid());
result.put("noncestr", noncestr);
result.put("timestamp", timestamp);
result.put("signature", signature);
return result;
}
- 控制器
/**
* 获取签名
* @param pageUrl 页面地址
*/
@RequestMapping(value = "/ticketSignature")
@ResponseBody
public JSONObject ticketSignature(@RequestParam(value = "pageUrl") String pageUrl){
return WeixinUtils.ticketSignture(pageUrl);
}