微信网页授权登录且实现access_token分布式管理
建议:一定要先看官方文档
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
注意事项和说明官方文档都有说明,我就不说了
两种方案:第一种原生代码,我这里说第二种sdk实现,github上面有很多优秀的sdk,这里只说其一
github sdk地址: https://github.com/Wechat-Group/weixin-java-tools/wiki
这是之前的版本,后面改名为 WXJava 了,对于新版的sdk,下面的代码有些已经不适用了,可更具新版sdk自行更改代码
本人拥有丰富的微信公众号开发和小程序开发以及支付开发经验,最近有点时间就打算写写博客
我使用的环境是springboot,ieda
使用方法:
1)第一步:
导包一一>maven或者gradle
maven:
<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>3.1.0</version>
</dependency>
gradle:
compile 'com.github.binarywang:weixin-java-mp:3.1.0'
2)第二部: 配置sdk的config
配置文件
yml中
official:appId: wx1c0abaaa92fbeef9appSecret: 5bf7cb8732af714d8540bbc5641f2df4
# host必须加http或httpshost: http://like.s1.natapp.cc
属性config:
package com.xiaoyu.tool.configs.property;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "official")
@Data
public class OfficialProperty {
private String appId;
private String appSecret;
private String host;
}configuration: 重写sdk方法,使用redis管理access_token,防止两小时内每调用一次sdk方法就刷新一次access_token,此方法在分布式中尤为重要且解决了微信接口调用次数的限制
package com.xiaoyu.tool.configs;
import com.xiaoyu.tool.configs.property.OfficialProperty;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;@Slf4j
@Configuration
@EnableConfigurationProperties(OfficialProperty.class)
public class WeixinMpConfiguration {
private final RedisTemplate<String, String> redisTemplate;
@Autowired
private OfficialProperty officialProperty;public WeixinMpConfiguration(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Bean
public WxMpService wxMpService(){
WxMpSpringRedisConfigStorage configStorage = new WxMpSpringRedisConfigStorage(redisTemplate);
configStorage.setAppId(officialProperty.getAppId());
configStorage.setSecret(officialProperty.getAppSecret());
WxMpService wxMpService = new WxMpServiceImpl();
wxMpService.setWxMpConfigStorage(configStorage);
return wxMpService;
}
}configStorage:重写sdk底层storage
package com.xiaoyu.tool.configs;import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import org.springframework.data.redis.core.RedisTemplate;import java.util.concurrent.TimeUnit;public class WxMpSpringRedisConfigStorage extends WxMpInMemoryConfigStorage {private final static String ACCESS_TOKEN_KEY = "wechat_access_token_";private final static String JSAPI_TICKET_KEY = "wechat_jsapi_ticket_";private final static String CARDAPI_TICKET_KEY = "wechat_cardapi_ticket_";private final RedisTemplate<String, String> redisTemplate;private String accessTokenKey;private String jsapiTicketKey;private String cardapiTicketKey;public WxMpSpringRedisConfigStorage(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;}@Overridepublic void setAppId(String appId) {super.setAppId(appId);
// 定义redis中存储的名称this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(appId);this.cardapiTicketKey = CARDAPI_TICKET_KEY.concat(appId);}@Overridepublic String getAccessToken() {return redisTemplate.opsForValue().get(this.accessTokenKey);}@Overridepublic boolean isAccessTokenExpired() {return redisTemplate.getExpire(this.accessTokenKey) < 2;}@Overridepublic synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {redisTemplate.opsForValue().set(this.accessTokenKey,accessToken,expiresInSeconds - 200, TimeUnit.SECONDS);}@Overridepublic void expireAccessToken() {redisTemplate.expire(this.accessTokenKey, 0, TimeUnit.SECONDS);}@Overridepublic String getJsapiTicket() {return redisTemplate.opsForValue().get(this.jsapiTicketKey);}@Overridepublic boolean isJsapiTicketExpired() {return redisTemplate.getExpire(this.jsapiTicketKey) < 2;}@Overridepublic synchronized void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {redisTemplate.opsForValue().set(this.jsapiTicketKey, jsapiTicket, expiresInSeconds - 200, TimeUnit.SECONDS);}@Overridepublic void expireJsapiTicket() {redisTemplate.expire(this.jsapiTicketKey, 0, TimeUnit.SECONDS);}@Overridepublic String getCardApiTicket() {return redisTemplate.opsForValue().get(this.cardapiTicketKey);}@Overridepublic boolean isCardApiTicketExpired() {return redisTemplate.getExpire(this.cardapiTicketKey) < 2;}@Overridepublic synchronized void updateCardApiTicket(String cardApiTicket, int expiresInSeconds) {redisTemplate.opsForValue().set(this.cardapiTicketKey, cardApiTicket, expiresInSeconds - 200, TimeUnit.SECONDS);}@Overridepublic void expireCardApiTicket() {redisTemplate.expire(this.cardapiTicketKey, 0, TimeUnit.SECONDS);}}
redis配置:
package com.xiaoyu.tool.configs;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;@ComponentScan
@Configuration
public class RedisConfiguration {@Beanpublic RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(new StringRedisSerializer());redisTemplate.afterPropertiesSet();return redisTemplate;}}
3)第三步:具体实现 controller代码
package com.xiaoyu.tool.controller.user;import com.xiaoyu.tool.configs.property.OfficialProperty;
import com.xiaoyu.tool.entity.User.User;
import com.xiaoyu.tool.service.user.UserWebAuthorizedService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.net.URLEncoder;/*** @Author:xiaoyu* @Created on 2018/9/17* @Description 公众号网页授权登录*/
@Controller
@RequestMapping(value = "/webAuthorized")
@Slf4j
public class UserWebAuthorizedController {private final OfficialProperty officialProperty;private final WxMpService wxMpService;private final UserWebAuthorizedService userWebAuthorizedService;public UserWebAuthorizedController(OfficialProperty officialProperty, WxMpService wxMpService, UserWebAuthorizedService userWebAuthorizedService) {this.officialProperty = officialProperty;this.wxMpService = wxMpService;this.userWebAuthorizedService = userWebAuthorizedService;}/***sdk 简单便捷*/@ApiOperation("微信网页授权")@GetMapping("/authorize")public String welcome(){//授权成功后跳转同域名下的网页String returnUrl = officialProperty.getHost() + "/index";//重定向的回调链接地址String url = officialProperty.getHost() + "/wechat_alipay_tool/webAuthorized/oauth2";String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, URLEncoder.encode(returnUrl));return "redirect:" + redirectUrl;}@ApiOperation("授权获取用户信息")@GetMapping("/oauth2")public String oauth2(@RequestParam(name = "code") String code,@RequestParam("state") String returnUrl) {try {WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(accessToken, "zh_CN");User user = userWebAuthorizedService.createAndUpdateUser(wxMpUser);log.info("用户信息:{}",user);} catch (WxErrorException e) {log.error("通过code获取accessToken失败/获取用户信息失败:{}",e.getMessage());}return "redirect:" + returnUrl;}}测试环境: 申请微信测试号,配置natapp域名穿透
微信测试号登录:
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login&token=1361182780&lang=zh_CN
配置:
这几个不要配置错了,根据自己的域名配置
natapp:
https://natapp.cn/
微信网页授权登录且实现access_token分布式管理相关推荐
- 微信公众号开发(一) 微信网页授权登录
微信网页授权登录 前期准备 授权登录 获取微信数据 处理授权拒绝 前期准备 1.微信公众号开发,首先要搞一个公众号,开发阶段可以申请一个公众平台测试账号. (进入到微信公众公众平台,找到开发者工具,点 ...
- php微信授权ajax,ajax 实现微信网页授权登录
项目背景 因为项目采用前后端完全分离方案,所以,无法使用常规的微信授权登录作法,需要采用 ajax 实现微信授权登录. 需求分析 因为本人是一个PHPer ,所以,微信开发采用的是 EasyWeCha ...
- java ajax 微信网页授权_ajax 实现微信网页授权登录的方法
AJAX 的 ajax 实现微信网页授权登录的方法 项目背景 因为项目采用前后端完全分离方案,所以,无法使用常规的微信授权登录作法,需要采用 ajax 实现微信授权登录. 需求分析 因为本人是一个ph ...
- 微信网页授权登录的方法
微信网页授权登录官方文档 微信网页授权登录的方法–推荐文章一 微信网页授权登录的方法–推荐文章二 总结: 微信授权方式(scope的属性值控制): 应用授权作用域,snsapi_base (不弹出授权 ...
- 微信网页授权登录java后台实现
建议先阅读微信开发-网页授权登录官方文档: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_au ...
- php微信登录代理转发,PHP微信网页授权登录
PHP微信网页授权登录 2018年04月10日 15:44:03阅读数:601 namespace Org\WeChat; /** * 微信授权相关接口 */ class Wechat { //高级功 ...
- Springboot + Spring Security多种登录方式:账号用户名登录+微信网页授权登录
一.概述 实现账号用户名+微信网页授权登录集成在Spring Security的思路,最重要的一点是要实现微信登录通过Spring Security安全框架时,不需要验证账号.密码. 二.准备工作 要 ...
- SpringBoot + Spring Security多种登录方式:账号+微信网页授权登录
一.概述 实现账号用户名+微信网页授权登录集成在Spring Security的思路,最重要的一点是要实现微信登录通过Spring Security安全框架时,不需要验证账号.密码. 二.准备工作 要 ...
- Spring Boot Security 多种登录方式集成配置思路及方法 账号用户名登录+微信网页授权登录
概述 实现账号用户名+微信网页授权登录集成在Spring Security的思路 前情提要 本思路完全抛弃Spring Security的配置式账号密码登录模式,采用完全独立的Filter.Provi ...
最新文章
- stm32 基本定时器TIM6、TIM7的使用
- Keyboard驱动中button中断的处理机制
- mysql命令行设置sqlmodel_MySQL的sql_mode模式说明及设置
- HTTP事务的延迟—TCP的影响
- 火山小视频尼尔森:2019新线消费市场人群洞察报告(附下载)
- Fedora 17 PHP编程环境配置
- oracle创建数据库用户并授权,oracle创建数据库、表空间、用户并授权
- netfilter与用户空间通信
- 如何让CSS动画中途停止并维持姿态
- ArcGIS API for JavaScript心得体验
- 启明星Exchange/outlook预定会议室终端显示解决方案
- JS简单获取猫眼电影所有城市完整的json数据(包括城市id和城市拼音)
- 读庄子-万物齐一和自然无为
- 7654劫持火狐解决办法
- cisco3560交换机的策略路由的设置
- 百度Java二面面经
- oracle存储过程初学实例
- 如何做一个优雅的Pod
- [思维模式-10]:《如何系统思考》-6- 认识篇 - 结构决定功能,如何进行深度思考
- 局域网steam联机_适合和基友联机一起玩的单机游戏(1)
热门文章
- pdffactory 打印字体_pdfFactory使用过程中的一些小技巧
- 美术-常用免费贴图网站分享
- python怎么表达我喜欢你_如何用含蓄的话表达我喜欢你 含蓄表达我喜欢你的句子大全...
- 安居客python二手房数据预处理
- 博士论文致谢火了!“我走了很远的路,吃了很多的苦,才将这份博士学位论文送到你的面前”!...
- 在局域网如何使用Git
- CSS3 动画卡顿性能优化解决方案--摘抄
- 基于SSM框架的湘潭大学二手物品交易平台
- 用python写期货程序-python如何运用在期货(我用python做期货)
- Linux系统之磁盘分区(基本分区和LVM逻辑卷分区)