目录
主要说明微信平台接口对接的记录文档与Java拦截器得使用。
微信
前置条件
微信公众平台获取唯一id:Appid,秘钥:secret,配置在application.yml文件中,并且加入所需jar包
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.2.3</version>
<classifier>jdk15</classifier>
</dependency>
接口调用器 RestTemplate
配置spring带的RestTemplate来调用Api
@Autowired
private RestTemplate restTemplate;
微信小程序获取jscode:
(1.uni-app框架搭建得小程序调用uni.login()
方法获取code。(参考链接)
(2.微信小程序框架调用wx.login()
方法获取code。(参考链接)
微信公众号获取jscode:
在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认拥有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
尤其注意:由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问
其中:
AppID- 公众号的唯一标识
REDIRECT_URI- 跳转url
SCOPE -值为snsapi_base(不弹出授权页面,直接跳转,只能获取用户openid) 或snsapi_userinfo (弹 出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
STATE- 开发者可以自定义填写a-zA-Z0-9的参数值
详情请访问微信官方文档
微信公众号
-
获取openId ,在获取到微信开发者平台的AppId,secret秘钥,与微信用户认证的jsCode;(参考链接)
备注:jscode是由前端用户访问地址时带过来的
//api调用工具类
@Autowired
private RestTemplate restTemplate;
/**
* 微信小程序api接口调用
*
* @param weChatDto 微信用户授权信息
* @return 返回获取了session_key的weChat对象
*/
public WeChatDto appletsLogin(WeChatDto weChatDto) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";
Map<String, String> requestMap = new HashMap<>();
requestMap.put("appid", weChatConfig.getAppid());
requestMap.put("secret", weChatConfig.getSecret());
requestMap.put("code", weChatDto.getJsCode());
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, requestMap);
JSONObject jsonObject = JSONObject.parseObject(responseEntity.getBody());
String openId = jsonObject.getString("openid");
if (StringUtils.isEmpty(openId)) {
throw new CustomException(jsonObject.toString(), Integer.valueOf(jsonObject.getString("errcode")));
}
//String accessToken = jsonObject.getString("access_token");暂时不用
//自定义方法用openId和session_key换取token
WeChatDto weChatDto1 = new WeChatDto();
weChatDto1.setOpenId(openId);
weChatDto1.setAppId(weChatConfig.getAppid());
return weChatDto1;
}
通过appid,secret,code,grant_type获取到微信返回的数据后使用com.alibaba.fastjson.JSONObject.parseObject()解析成json,通过key/value形式读取数据并返回关键数据
- 获取access_token,token分为网页请求token与基础token,微信开发者平台需要将Ip和域名加入白名单;(参考链接)
public WeChatDto userInfo(String openId, String accessToken, String lang) {
//初始化修改restTemplate编码
StringHttpMessageConverter stringHttpMessageConver = new StringHttpMessageConverter(Charset.forName("UTF-8"));
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
//通过微信授权获取基础accessToken
String userInfoUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}";
Map<String, String> userInfoRequestMap = new HashMap<>();
userInfoRequestMap.put("appid", weChatConfig.getAppid());
userInfoRequestMap.put("secret", weChatConfig.getSecret());
ResponseEntity<String> userInfoResponseEntity = restTemplate.getForEntity(userInfoUrl, String.class, userInfoRequestMap);
JSONObject userInfoJsonObject = JSONObject.parseObject(userInfoResponseEntity.getBody());
String accessTokenNew = userInfoJsonObject.getString("access_token");
if (StringUtils.isEmpty(accessTokenNew)) {
throw new CustomException(userInfoJsonObject.toString(), Integer.valueOf(userInfoJsonObject.getString("errcode")));
}
log.error("===============================================================:" + userInfoJsonObject);
通过appid,secret,grant_type获取到微信返回的数据后,同样使用JSONObject来解析获取access_token并传值返回
- 第一个接口拿到openid,第二个接口拿到基础token,再调用获取用户信息的接口,就能获取到完整的用户信息(手机号除外);(参考链接)
//使用用户唯一openid和基础accessToken获取完整用户信息
String url = "https://api.weixin.qq.com/cgi-bin/user/info?openid={openid}&access_token={access_token}&lang={lang}";
Map<String, String> requestMap = new HashMap<>();
requestMap.put("openid", openId);
requestMap.put("access_token", accessTokenNew);
requestMap.put("lang", "zh_CN");
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, requestMap);
JSONObject jsonObject = JSONObject.parseObject(responseEntity.getBody());
log.error("===============================================================:" + jsonObject);
通过获取到的openid和access_token获取到微信用户的信息,解析成json后通过key/value取值。
备注:以上功能,需要前端传值jscode,前端页面需要用户允许授权调用接口等配合,此处只说明后端!
h5拦截器
若依系统为例,业务需求是在不影响后台权限控制的情况下,重新配置一个公众号h5页面的权限控制,生产一个h5的token进行认证。需要使用redis(这里不多赘述redis的使用,感兴趣者可以去下载若依系统)。
# token配置
token:
# 令牌自定义标识
header: 123456
# 令牌密钥
secret: 123456
# 令牌有效期(默认60分钟)
expireTime: 60
先将若依系统的拦截器把h5相关接口开放出来不拦截,再加入到自定义的拦截器里进行拦截和开放
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 微信H5端拦截器
*/
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Bean
ShopUserActivityInterceptor getShopUserActivityInterceptor() {
return new ShopUserActivityInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册TestInterceptor拦截器
InterceptorRegistration registration = registry.addInterceptor(getShopUserActivityInterceptor())