微信测试号申请:
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
微信公众号接口调试平台:
https://mp.weixin.qq.com/debug/
NATAPP内网穿透:
https://natapp.cn/
1、申请测试号、按指引操作即可。
使用内网穿透生成的域名。
2、接口配置
2.1工具类
package com.wx.project.util;
import java.security.MessageDigest;
import java.util.Arrays;
public class WxLinkUtil {
public static boolean checkSignature(String signature,String timestamp,String nonce){
String[] arr = new String[]{"test_weixin",timestamp,nonce};
Arrays.sort(arr);
StringBuffer content = new StringBuffer();
for (int i = 0;i < arr.length;i++){
content.append(arr[i]);
}
MessageDigest md = null;
String temStr = null;
try {
md = MessageDigest.getInstance("SHA-1");
byte[] digest = md.digest(content.toString().getBytes());
temStr = byteToStr(digest);
}catch (Exception e){
e.printStackTrace();
}
content = null;
return temStr != null ? temStr.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转换为十六进制字符串
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
2.2 接口
package com.wx.project.controller;
import com.wx.project.util.WxLinkUtil;
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("/wx")
public class WXController {
@RequestMapping(value = "/link",method = RequestMethod.GET)
public void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
//签名
String signature = request.getParameter("signature");
//时间戳
String timstamp = request.getParameter("timestamp");
//随机数
String nonce = request.getParameter("nonce");
//随机字符串
String echostr = request.getParameter("echostr");
if(WxLinkUtil.checkSignature(signature,timstamp,nonce)){
System.out.println("验证成功");
PrintWriter out = response.getWriter();
out.print(echostr);
out.close();
}else{
System.out.println("验证失败");
}
}
@RequestMapping(value = "/link",method = RequestMethod.POST)
public void DoPost(){
//不接管公众号的回复功能
}
}
3、设置公众号菜单
3.1 获取accesstoken
3.2 设置菜单
自定义菜单json串
{
"button": [
{
"name": "测试菜单",
"sub_button": [
{
"type": "view",
"name": "我是会员",
"url": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=【你的APPId】&redirect_uri=http%3a%2f%2f【你的域名】%2f【你的工程名】%2f【如登录接口】?&response_type=code&scope=snsapi_base&state=123#wechat_redirect "
}
]
}
]
}
4、登录接口-获取openId
/**
* 微信端点击进入的url.进行数据校验及跳转
*/
@Controller
@RequestMapping("/index")
public class IndexController {
@Autowired
private UserServiceImpl userService;
@Autowired
private MessageServiceImpl messageService;
@RequestMapping("/login")
public String login(HttpServletRequest request){
HttpSession session = request.getSession();
String code = request.getParameter("code");
//通过code换取openId
String responseStr = AccessTokenUtil.getOpenId(code);
JSONObject jsonObject = JSONObject.fromObject(responseStr);
//access_token
String access_token = (String) jsonObject.get("access_token");
//用户标识码
String openId = (String) jsonObject.get("openid");
System.out.println("openId :"+openId );
if(access_token != null && openId !=null && access_token != "" && openId != ""){
//获取微信用户的个人资料
String responseStr2 = AccessTokenUtil.getUserInfo(openId);
JSONObject jsonObject1 = JSONObject.fromObject(responseStr2);
System.out.println(jsonObject1);
}else{
//跳转至错误页面
return "redirect:/error.html";
}
}
5. 相关类
5.1 公众号相关工具类
package com.wx.project.util;
import com.wx.project.bean.AccessToken;
import com.wx.project.bean.WXPro;
import com.wx.project.service.impl.AccessTokenServiceImpl;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.client.RestTemplate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 公众号接口工具类
*/
public class AccessTokenUtil {
private static final String APPID = "wx82ba212c*******";
private static final String APPSECRET = "4eb0472113314**************";
private static ApplicationContext applicationContext = SpringUtils.getApplicationContext();
private static RestTemplate restTemplate = applicationContext.getBean(RestTemplate.class);
private static WXPro wxPro = applicationContext.getBean(WXPro.class);
private static AccessTokenServiceImpl accessTokenService = applicationContext.getBean(AccessTokenServiceImpl.class);
/**
* 获取accessToken.
* accessToken过期时间为2小时,并且有获取次数限制,故存入数据库
* @return
*/
public static String getAccessToken() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String accessToken = "";
try {
AccessToken at = accessTokenService.getAccessToken();
long currentTime = System.currentTimeMillis()/1000;//当前时间
long getTime = sdf.parse(at.getUpdateTime()).getTime()/1000;
long expiresIn = at.getExpired();
if(currentTime - getTime > expiresIn){
System.out.println("accessToken已过期,重新获取");
//accessToken已过期,重新获取
String url = wxPro.getTokenUrl().replace("APPID",APPID).replace("APPSECRET",APPSECRET);
String responseStr = (String) HttpUtil.sendGet(restTemplate,url);
JSONObject jsonObject = JSONObject.fromObject(responseStr);
accessToken = (String) jsonObject.get("access_token");
//获取到的accessToken存入数据库
AccessToken accessToken1 = new AccessToken();
accessToken1.setAccessToken(accessToken);
accessToken1.setUpdateTime(sdf.format(new Date()));
accessTokenService.updateAccessToken(accessToken1);
}else{
System.out.println("accessToken未过期,继续使用");
accessToken = at.getAccessToken();
}
} catch (ParseException e) {
e.printStackTrace();
}
return accessToken;
}
/**
* 通过openId获取用户信息
* @param openId
* @return
*/
public static String getUserInfo(String openId){
String url = wxPro.getUserInfoUrl().replace("ACCESS_TOKEN",getAccessToken()).replace("OPENID",openId);
String responseStr = (String) HttpUtil.sendGet(restTemplate,url);
return responseStr;
}
/**
* 通过code换取openId
* @param code
* @return
*/
public static String getOpenId(String code){
String url = wxPro.getOpenIdUrl().replace("APPID",APPID).replace("APPSECRET",APPSECRET).replace("CODE",code);
String responseStr = (String) HttpUtil.sendGet(restTemplate,url);
return responseStr;
}
}
5.2 accessToken实体类
package com.wx.project.bean;
public class AccessToken {
private int id;
private String accessToken;
private int expired;
private String updateTime;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpired() {
return expired;
}
public void setExpired(int expired) {
this.expired = expired;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
}
5.3 接口地址配置文件
wx.properties
#获取accesstoken
wxpro.tokenUrl = https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
#通过code换取openId
wxpro.openIdUrl = https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code
#通过openId获取用户信息
wxpro.userInfoUrl = https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
接口地址实体
package com.wx.project.bean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "wxpro")
@PropertySource("classpath:wx.properties")
public class WXPro {
private String tokenUrl;
private String userInfoUrl;
private String openIdUrl;
public String getTokenUrl() {
return tokenUrl;
}
public void setTokenUrl(String tokenUrl) {
this.tokenUrl = tokenUrl;
}
public String getUserInfoUrl() {
return userInfoUrl;
}
public void setUserInfoUrl(String userInfoUrl) {
this.userInfoUrl = userInfoUrl;
}
public String getOpenIdUrl() {
return openIdUrl;
}
public void setOpenIdUrl(String openIdUrl) {
this.openIdUrl = openIdUrl;
}
}
至此。点击测试公众号上的菜单进入即可获取到用户信息。
菜鸡一枚,如有错误,麻烦指出。有疑问可留言