diff --git a/src/main/java/cn/itsource/config/interceptor/LoginInterceptor.java b/src/main/java/cn/itsource/config/interceptor/LoginInterceptor.java index 1625232ab6daa3f078d46b68ab52a970e4b48a32..b6cbfc0533a7653fc2899e5ce1cfb0ceea57e58a 100644 --- a/src/main/java/cn/itsource/config/interceptor/LoginInterceptor.java +++ b/src/main/java/cn/itsource/config/interceptor/LoginInterceptor.java @@ -22,12 +22,16 @@ public class LoginInterceptor implements HandlerInterceptor { @Autowired private RedisService redisService; + + /** * 进入目标方法(Controller的方法)之前之前,false:拦截 true:放行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + System.out.println("----------------"+request.getRequestURI()); + //告诉浏览器我返回的数据按json来解析 response.setContentType("application/json;charset=utf-8"); diff --git a/src/main/java/cn/itsource/config/interceptor/PetHomeMvcConfig.java b/src/main/java/cn/itsource/config/interceptor/PetHomeMvcConfig.java index 4cbc471543a72e94ca5f96d7923caadb650a2241..688de7550eedfc2ef8f0982637f72dfc557fe88c 100644 --- a/src/main/java/cn/itsource/config/interceptor/PetHomeMvcConfig.java +++ b/src/main/java/cn/itsource/config/interceptor/PetHomeMvcConfig.java @@ -25,7 +25,7 @@ public class PetHomeMvcConfig implements WebMvcConfigurer { registry.addInterceptor(loginInterceptor) .addPathPatterns("/**") //拦截所有 .excludePathPatterns("/**/login", "/shop/settlement", "/file/**" - , "/user/**")//放行 + , "/user/**","/wechart/**")//放行 .excludePathPatterns("/swagger-resources/**" , "/webjars/**" , "/v2/**" diff --git a/src/main/java/cn/itsource/wechart/controller/WeChartController.java b/src/main/java/cn/itsource/wechart/controller/WeChartController.java new file mode 100644 index 0000000000000000000000000000000000000000..acb64e5ce16440c8806386e5d96506c03dbf207f --- /dev/null +++ b/src/main/java/cn/itsource/wechart/controller/WeChartController.java @@ -0,0 +1,74 @@ +package cn.itsource.wechart.controller; + +import cn.itsource.basic.util.AjaxResult; +import cn.itsource.wechart.pojo.domain.WechartProperties; +import cn.itsource.wechart.pojo.dto.BinderDto; +import cn.itsource.wechart.service.IWeChartService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +@Controller +@RequestMapping("/wechart") +public class WeChartController { + + @Autowired + private WechartProperties wechartProperties; + + @Autowired + private IWeChartService weChartService; + + + /** + * 点页面的”微信登录“进来的 + * + * @return + */ + @GetMapping("/tologin") + public String toLogin() { + return weChartService.toLogin(); + } + + /** + * 扫码进来的 + * + * @param code + */ + @GetMapping("callback") + public String callback(String code) { + //调用service + return weChartService.callback(code); + } + + /** + * 绑定的接口 + */ + @PostMapping("/binder") + @ResponseBody + public AjaxResult binder(@RequestBody BinderDto binderDto) { + //调用service + return weChartService.binder(binderDto); + } + + + @RequestMapping("/test") + public void test() { + + System.err.println(wechartProperties); + + } + + + public static void main(String[] args) { + //解耦 + String appid = "wxd853562a0548a7d0"; + + String appsecrect = "4a5d5615f93f24bdba2ba8534642dbb6"; + String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s"; + + // %s:占位符 + String format = String.format(url, appid, appsecrect); + System.out.println(format); + //https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxd853562a0548a7d0&secret=4a5d5615f93f24bdba2ba8534642dbb6 + } +} diff --git a/src/main/java/cn/itsource/wechart/mapper/WxUserMapper.java b/src/main/java/cn/itsource/wechart/mapper/WxUserMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..3cda0947eab5ca1c0716d10d91c96f212510ebf2 --- /dev/null +++ b/src/main/java/cn/itsource/wechart/mapper/WxUserMapper.java @@ -0,0 +1,15 @@ +package cn.itsource.wechart.mapper; + +import cn.itsource.basic.basicmapper.BasicMapper; +import cn.itsource.wechart.pojo.domain.WxUser; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +public interface WxUserMapper extends BasicMapper { + + + @Select("select * from t_wxuser where openid = #{openid}") + WxUser findByOpenid(String openid); + + void updateUserIdByOenid(@Param("userId") Long userId, @Param("openid") String openid); +} diff --git a/src/main/java/cn/itsource/wechart/pojo/domain/WechartProperties.java b/src/main/java/cn/itsource/wechart/pojo/domain/WechartProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..7ce3caa9311b60d4ee58f3887d13bc44eafd88d3 --- /dev/null +++ b/src/main/java/cn/itsource/wechart/pojo/domain/WechartProperties.java @@ -0,0 +1,18 @@ +package cn.itsource.wechart.pojo.domain; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Data +@Component //交给spring管理了 +@ConfigurationProperties("pethome.wechart") +public class WechartProperties { + private String tokenUrl; + private String authorizationCodeUrl; + private String userinfoUrl; + private String refreshTokenUrl; + private String appId; + private String appSecrect; + private String redirectUri; +} \ No newline at end of file diff --git a/src/main/java/cn/itsource/wechart/pojo/domain/WxUser.java b/src/main/java/cn/itsource/wechart/pojo/domain/WxUser.java new file mode 100644 index 0000000000000000000000000000000000000000..f3478ee6a00f8898bb3034c99ae3a6c3d0c6b777 --- /dev/null +++ b/src/main/java/cn/itsource/wechart/pojo/domain/WxUser.java @@ -0,0 +1,31 @@ +package cn.itsource.wechart.pojo.domain; + +import cn.itsource.basic.domain.BaseDomain; +import io.swagger.annotations.ApiModel; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Table; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "t_wxuser") +public class WxUser extends BaseDomain { + //微信账户唯一标识 + private String openid; + //昵称 + private String nickname; + //性别 + private Integer sex; + //地址 + private String address; + //头像 + private String headimgurl; + //联盟id(没用) + private String unionid; + //对应平台的t_user表的id + private Long userId; + +} diff --git a/src/main/java/cn/itsource/wechart/pojo/dto/BinderDto.java b/src/main/java/cn/itsource/wechart/pojo/dto/BinderDto.java new file mode 100644 index 0000000000000000000000000000000000000000..50346fc48b03de4d111e58615446dca152a9be3f --- /dev/null +++ b/src/main/java/cn/itsource/wechart/pojo/dto/BinderDto.java @@ -0,0 +1,13 @@ +package cn.itsource.wechart.pojo.dto; + +import lombok.Data; + +@Data +public class BinderDto { + //手机号 + private String phone; + //验证码 + private String code; + //openid + private String openid; +} diff --git a/src/main/java/cn/itsource/wechart/pojo/dto/WechartTokenDto.java b/src/main/java/cn/itsource/wechart/pojo/dto/WechartTokenDto.java new file mode 100644 index 0000000000000000000000000000000000000000..bdbb1849976bf6374f12bd9414c031416dc45d70 --- /dev/null +++ b/src/main/java/cn/itsource/wechart/pojo/dto/WechartTokenDto.java @@ -0,0 +1,20 @@ +package cn.itsource.wechart.pojo.dto; + +import lombok.Data; + +//微信获取Token返回结果 +@Data +public class WechartTokenDto { + //{"access_token":"44_QfGkFOzewXRoLFGjydhphpo0O6n3sLnRKQlUyUFf0x-LIxMLcSIPiLkeYEKWyt_rx93-XYUuRu4QGwUFstFBO2gfUTOS1Q4D7g2IDM30Bc8", + // "expires_in":7200, + // "refresh_token":"44_9xsOalBhPa98SRnxbuWWNadc8wW3rQFgbRgsrNIp-wSuC3r4cYzSQ5b9oJAICcennhis5oY6p5cdKnHreEW-B_WPTRDIqzcHC8ZccMHOxUY", + // "openid":"oa9wA06iSpmWAF5YO-WjATExOQvw", + // "scope":"snsapi_login", + // "unionid":"ovnCWw1NSHHr6EkoPiBF3S68ah-k"} + private String access_token; + private Integer expires_in; + private String refresh_token; + private String openid; + private String scope; + private String unionid; +} \ No newline at end of file diff --git a/src/main/java/cn/itsource/wechart/pojo/dto/WechartUserInfoDto.java b/src/main/java/cn/itsource/wechart/pojo/dto/WechartUserInfoDto.java new file mode 100644 index 0000000000000000000000000000000000000000..58383f98c19d5624e954149b8a05e153905ae92c --- /dev/null +++ b/src/main/java/cn/itsource/wechart/pojo/dto/WechartUserInfoDto.java @@ -0,0 +1,19 @@ +package cn.itsource.wechart.pojo.dto; + +import lombok.Data; + +import java.util.List; + +//微信个人信息结果参数封装 +@Data +public class WechartUserInfoDto { + private String openid; + private String nickname; + private Integer sex; + private String province; + private String city; + private String country; + private String headimgurl; + private String unionid; + private List privilege; +} \ No newline at end of file diff --git a/src/main/java/cn/itsource/wechart/service/IWeChartService.java b/src/main/java/cn/itsource/wechart/service/IWeChartService.java new file mode 100644 index 0000000000000000000000000000000000000000..6e2ebb1cf951deac896ffc2155fc9068c66861c6 --- /dev/null +++ b/src/main/java/cn/itsource/wechart/service/IWeChartService.java @@ -0,0 +1,12 @@ +package cn.itsource.wechart.service; + +import cn.itsource.basic.util.AjaxResult; +import cn.itsource.wechart.pojo.dto.BinderDto; + +public interface IWeChartService { + String toLogin(); + + String callback(String code); + + AjaxResult binder(BinderDto binderDto); +} diff --git a/src/main/java/cn/itsource/wechart/service/impl/WechartServiceImpl.java b/src/main/java/cn/itsource/wechart/service/impl/WechartServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..a8daa6346ab69961bb4b47bafb39999a00c80d12 --- /dev/null +++ b/src/main/java/cn/itsource/wechart/service/impl/WechartServiceImpl.java @@ -0,0 +1,176 @@ +package cn.itsource.wechart.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.itsource.basic.util.AjaxResult; +import cn.itsource.basic.util.RedisService; +import cn.itsource.config.exception.BusinessException; +import cn.itsource.org.domain.User; +import cn.itsource.org.mapper.UserMapper; +import cn.itsource.org.service.IUserService; +import cn.itsource.org.vo.LoginVo; +import cn.itsource.wechart.mapper.WxUserMapper; +import cn.itsource.wechart.pojo.domain.WechartProperties; +import cn.itsource.wechart.pojo.domain.WxUser; +import cn.itsource.wechart.pojo.dto.BinderDto; +import cn.itsource.wechart.pojo.dto.WechartTokenDto; +import cn.itsource.wechart.pojo.dto.WechartUserInfoDto; +import cn.itsource.wechart.service.IWeChartService; +import com.alibaba.fastjson.JSONObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import tk.mybatis.mapper.entity.Example; + +/** + * 微信业务 + */ +@Service +public class WechartServiceImpl implements IWeChartService { + + @Autowired + private WechartProperties wechartProperties; + + @Autowired + private WxUserMapper wxUserMapper; + + @Autowired + private IUserService userService; + + @Autowired + private UserMapper userMapper; + + @Autowired + private RedisService redisService; + + @Override + public String toLogin() { + //https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect" + + //步骤一,跳转到扫描的页码 + //1.获取到url + String codeUrl = wechartProperties.getAuthorizationCodeUrl(); + //2.进行String format操作 + String s = String.format(codeUrl, wechartProperties.getAppId(), wechartProperties.getRedirectUri(), IdUtil.fastSimpleUUID()); + //3.重定向 + return "redirect:"+s; + } + + @Override + public String callback(String code) { + //步骤二,通过code获取access_token + //1.拿到获取token的url + //https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code + String tokenUrl = wechartProperties.getTokenUrl(); + + //2.拼接url,替换%s + tokenUrl = String.format(tokenUrl,wechartProperties.getAppId(),wechartProperties.getAppSecrect(), code); + + //3.用java代码访问这个拼接好的url + String result = HttpUtil.get(tokenUrl); + //{"access_token":"61_RUM4lyYfxVfPoZksYK6Drdm-QnncltDoL83jkk8CL1mk4eE90IZjCeG7aA3_5pknRtT_x3ls9MONxIozDDc62npZs3WnsTVPVQaB5iOq3Tk","expires_in":7200,"refresh_token":"61_we-NEY4GboccEhfSVDwkKMYznOJw7gvbE5kvsTAZY14oLKLc9fk8bWjRjzvt6ogRy9jkwS5uUzgjGs_AK6PzaptPOYqvJFeXINVNNLAVCFw","openid":"oa9wA090OrSqsxy8AHbPk1qxc2uM","scope":"snsapi_login","unionid":"ovnCWw7rqhgKc0LcWhi9rPRmhb4s"} + System.out.println(result); + //4.把json字符串的数据封装到dto中 + WechartTokenDto wechartTokenDto = JSONObject.parseObject(result, WechartTokenDto.class); + System.out.println(wechartTokenDto); //包含 access_token和openid + + //步骤三,获取微信三方用户信息 + //1.获取url //https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s" + String userinfoUrl = wechartProperties.getUserinfoUrl(); + //2.处理%s + userinfoUrl = String.format(userinfoUrl, wechartTokenDto.getAccess_token(), wechartTokenDto.getOpenid()); + + //3.发get请求获取用户的信息 + String infoResult = HttpUtil.get(userinfoUrl); + System.out.println(infoResult);//json串 openid:唯一标识 + + //4.解析json字符串,到dto中 + WechartUserInfoDto infoDto = JSONObject.parseObject(infoResult, WechartUserInfoDto.class); + + System.out.println(infoDto); + + //----------------------------上面是调用微信开放平台接口,下面把微信信息绑定平台账户---------------------------------------------------------------- + /** + * openid在每个企业账户下,每个人是唯一的,同一个人在同一个企业账号下扫描openid就是独一无二的 + * 通过分析,得到3种情况进行处理 + * 1.通过openid在t_wxuser表拿不到数据源 + * 1.1新增t_wxuser的一行数据 + * 1.2去绑定页面进行绑定 + * 2.所有的数据都是ok的 t_wxuser有user_id t_user有手机号 + * 1.2跳转到平台首页 + * 3.其他情况 + * 3.1全部去绑定页面(binder.html) + */ + String binderHtmlUrl = "http://localhost:8081/binder.html"; + + //1.获取openid,根据openid匹配数据 + String openid = infoDto.getOpenid(); + WxUser wxUser = wxUserMapper.findByOpenid(openid); + //2.判断微信user是否存在 + if (wxUser == null){ + WxUser dbWxUser = BeanUtil.copyProperties(infoDto, WxUser.class); + //入库 + wxUserMapper.insertSelective(dbWxUser); + //跳转到绑定页面 + return "redirect:"+binderHtmlUrl+"?openid="+openid; + } + + //处理情况2 + Long userId = wxUser.getUserId(); + if (userId != null){ + //1.查user对象 + User dbUser = userService.findOne(userId); + //2.如果数据完整 + if (dbUser != null && StrUtil.isNotBlank(dbUser.getPhone())){ + //需要穿token和登录信息 + //生成token,存到redis,返回页面 + String token = IdUtil.fastSimpleUUID(); + LoginVo loginVo = new LoginVo(); + loginVo.setToken(token); + redisService.setStringKeyAndValue(token,loginVo,30); + + return "redirect:http://localhost:8081/index.html?phone="+dbUser.getPhone()+"&token="+token; + } + } + + //其他情况全部去绑定页面 + return "redirect:"+binderHtmlUrl+"?openid="+openid; + } + + @Override + public AjaxResult binder(BinderDto binderDto) { + //0.验证code + /*if (!StrUtil.equals(binderDto.getCode(),redisService.getKeyStringValue(binderDto.getPhone()))){ + throw new BusinessException("验证码错误"); + }*/ + + //1.获取phone ,通过phone获取user对象 + String phone = binderDto.getPhone(); + User dbPhone = userMapper.findByPhone(phone); + //2.份两种情况 + //dbPhone不存在 1.新增user数据 2.拿到自增id 3.修改wxUser的user_id + Long userId = null; + if (dbPhone == null){ + User user = new User(); + user.setPhone(phone); + user.md5Pwd();//加盐加密 + userMapper.insertSelective(user); + userId = user.getId(); + }else{ + userId = dbPhone.getId(); + } + + //存在,拿到userId,修改wxUser的user_id + wxUserMapper.updateUserIdByOenid(userId,binderDto.getOpenid()); + + //生成token,存到redis,返回页面 + String token = IdUtil.fastSimpleUUID(); + LoginVo loginVo = new LoginVo(); + loginVo.setPhone(phone); + loginVo.setToken(token); + redisService.setStringKeyAndValue(token,loginVo,30); + + return AjaxResult.createSuccess(loginVo); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9ecde64c87e2f85836202c0c9312582be7771163..e6cdfa72ea8c788d19a21fea899d40170f10d939 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -37,4 +37,22 @@ mybatis: logging: level: cn: - itsource: debug \ No newline at end of file + itsource: debug + +# 解耦 +pethome: + wechart: + #1.获取授权码URL + authorization-code-url: "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=%s#wechat_redirect" + #2.获取Token的URL + token-url: "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" + #3.获取用户信息 URL + userinfo-url: "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s" + #刷新Token的 URL + refresh-token-url: "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s" + # 应用ID 源码时代提供的 + app-id: "wxd853562a0548a7d0" + # 应用秘钥 源码时代提供的 + app-secrect: "4a5d5615f93f24bdba2ba8534642dbb6" + # 授权码回调接口,对应我们平台的controller + redirect-uri: "http://bugtracker.itsource.cn/wechart/callback" \ No newline at end of file diff --git a/src/main/resources/cn/itsource/wechart/mapper/WxUserMapper.xml b/src/main/resources/cn/itsource/wechart/mapper/WxUserMapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..42345ac07e7a364731d9b951613a9cdf9e3e8168 --- /dev/null +++ b/src/main/resources/cn/itsource/wechart/mapper/WxUserMapper.xml @@ -0,0 +1,12 @@ + + + + + + update t_wxuser set user_id = #{userId} + where openid = #{openid} + + + \ No newline at end of file