上节写了配置地址到微信公众平台,这次写获取AccessToken
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。 复制代码
网络异常,图片无法展示
|
由接口文档可以看出获取Access token 需要GET请求并上送grant_type、appid、secret。 其中grant_type 上送默认值: client_credential 而appid、secret在公众平台首页
网络异常,图片无法展示
|
可以先通过微信公众平台接口调试工具进行调试,可以看到返回access_token(获取到的凭证)、以及expires_in (凭证有效时间,单位:秒)
网络异常,图片无法展示
|
网络异常,图片无法展示
|
创建 AccessTokenBean 对象
import lombok.Getter; import java.io.Serializable; import java.util.HashMap; /** * @Author : lizzu * @create 2022/9/24 21:35 * access token 对象 */ @Getter public class AccessTokenBean implements Serializable { /** * grant_type 固定值,直接填写client_credential */ private String grant_type = "client_credential"; /** * appID 用户的唯一标识 */ private String appid; /** * secret 用户唯一凭证密钥 */ private String secret; /** * 获取到的access token */ private String accessToken; /** * access token 过期时间 */ private long expiresTime; private AccessTokenBean(String appid, String secret, String accessToken, long expiresTime) { this.appid = appid; this.secret = secret; this.accessToken = accessToken; //失效时间 返回单位:秒 //判断失效处理时方便判断 if (expiresTime>0){ this.expiresTime = System.currentTimeMillis()+expiresTime*1000; } } /** * 构建获取access token 请求对象 * * @param appId 用户唯一标识 * @param secret 用户唯一标识密钥 * @return {@link HashMap} */ public static HashMap<String, String> requestOf(String appId, String secret) { HashMap<String, String> requestMap =new HashMap<>(16);//16为默认初始值 requestMap.put("appid",appId); requestMap.put("secret",secret); requestMap.put("grant_type", "client_credential"); return requestMap; } /** * 构建AccessToken 对象 * * @param accessToken token * @param expiresTime 过期时间 * @return {@link AccessTokenBean} */ public static AccessTokenBean responseOf(String accessToken, long expiresTime) { return new AccessTokenBean("", "", accessToken, expiresTime); } /** * 判断token是否已经失效 * * @return 是否失效 false 未失效 true 失效,需要重新申请 */ public boolean isExpired() { return System.currentTimeMillis() > expiresTime; } } 复制代码
将appid、secret参数放到配置类中 WeCharConfig
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * @Author : lizzu * @create 2022/9/24 21:37 */ @Component @Data @ConfigurationProperties(prefix = "we-char") public class WeCharConfig { /** * 用户唯一标识 */ private String appId; /** * 用户密钥 */ private String secret; /** * 加密token */ private String token; } 复制代码
配置文件application.yml
application: name: my-spring-wechar server: port: 8085 we-char: app-id: 你的app-id secret: 你的secret token: 你的token 复制代码
访问路径实体类WeCharConstant
/** * @Author : lizzu * @create 2022/9/25 15:15 */ public class WeCharConstant { /** * 获取Token */ public static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token"; } 复制代码
AccessTokenService,在获取方法中判断accessTokenBean 是否已经生成或已过期。当未生成或已过期时调用重新生成Token方法
import cn.org.spring.common.util.HttpClientUtils; import com.alibaba.fastjson.JSONObject; import com.ctsi.sddx.bean.AccessTokenBean; import com.ctsi.sddx.config.WeCharConfig; import com.ctsi.sddx.constants.WeCharConstant; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.IOException; /** * @Author : lizzu * @create 2022/9/24 21:51 */ @Service public class AccessTokenService { @Resource WeCharConfig weCharConfig; /** * access token 对象 */ private AccessTokenBean accessTokenBean; private static final String URL = WeCharConstant.GET_TOKEN_URL; /** * 获取access token * * @param appId * @param appSecret */ private void refreshAccessToken(String appId, String appSecret) throws IOException { String s = HttpClientUtils.get(URL, AccessTokenBean.requestOf(appId, appSecret)); JSONObject jsonObject = JSONObject.parseObject(s); long expiresIn = jsonObject.getLong("expires_in"); String accessToken = jsonObject.getString("access_token"); accessTokenBean = AccessTokenBean.responseOf(accessToken, expiresIn); } /** * 获取access token * * @return */ public String getAccessToken() throws IOException { if (accessTokenBean==null||accessTokenBean.isExpired()){ refreshAccessToken(weCharConfig.getAppId(), weCharConfig.getSecret()); } return accessTokenBean.getAccessToken(); } } 复制代码
WeCharController 测试
import cn.org.spring.common.util.XmlUtils; import com.ctsi.sddx.bean.message.TextMessage; import com.ctsi.sddx.service.AccessTokenService; import com.ctsi.sddx.utils.AccessAuthentication; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.io.IOException; import java.util.Map; /** * @Author : lizzu * @create 2022/9/24 20:26 */ @RestController @RequestMapping("/v1/weChart") public class WeCharController { private String token = "lizzuabc123123"; @Resource AccessTokenService accessTokenService; //接口测试 @PostMapping("/info") public String getInfo(){ return "hello word ! "; } @GetMapping public String getWeChar(@RequestParam String signature, @RequestParam String timestamp, @RequestParam String nonce, @RequestParam String echostr) { System.out.println("signature :" + signature); System.out.println("timestamp :" + timestamp); System.out.println("nonce :" + nonce); System.out.println("echostr :" + echostr); if (AccessAuthentication.of(token, timestamp, nonce, signature).checkSignature()) { return echostr; } return null; } @GetMapping("/getAccessToken") public String getAccessToken () throws IOException { String accessToken = accessTokenService.getAccessToken(); return accessToken; } 复制代码
网络异常,图片无法展示
|
到此获取Access token完成
下一篇: 自定义菜单