package com.xkrs.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.xkrs.common.config.ConstantConfig; import com.xkrs.common.encapsulation.PromptMessageEnum; import com.xkrs.dao.WeChatCodeDao; import com.xkrs.model.entity.WeChatCode; import com.xkrs.utils.HttpClientUtil; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.net.URLEncoder; import java.util.HashMap; import java.util.Locale; import static com.xkrs.common.encapsulation.OutputEncapsulation.outputEncapsulationObject; /** * @author XinYi Song * 微信扫码登录 */ @RestController public class WeChatController { @Resource private WeChatCodeDao weChatCodeDao; @GetMapping("/callback") public String callback(@RequestParam("code") String code, String state) throws Exception { Locale locale = LocaleContextHolder.getLocale(); try{ //1.获取code值,临时票据,类似于验证码 System.out.println(code); //2.拿着code请求微信固定的地址,得到两个值access_token和openid String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" + "?appid=%s" + "&secret=%s" + "&code=%s" + "&grant_type=authorization_code"; String accessTokenUrl = String.format(baseAccessTokenUrl, ConstantConfig.WX_OPEN_APP_ID, ConstantConfig.WX_OPEN_APP_SECRET, code); //请求这个拼接好的地址得到返回的值,现在请求地址,不用浏览器了,用httpclient发送一个请求得到一个返回的地址 String accessTokenInfo = HttpClientUtil.doGet(accessTokenUrl); //所以我们需要对字符串进行分割,先将字符串转换成map集合,map是key-value结构,再根据map中的key得到结果,这里我们用gson JSONObject jsonObject = JSON.parseObject(accessTokenInfo); String access_token =(String) jsonObject.get("access_token"); String openid = (String)jsonObject.get("openid"); //扫码人信息加到数据库中去 //判断数据库中是否存在相同的数据库信息,我们可以根据openid来做判断 WeChatCode byOpenId = weChatCodeDao.findByOpenId(openid); if (byOpenId ==null){ //member为空,表示数据库中没有相同的信息 //3.拿到access_token和openid,再去请求微信提供固定的地址,获取到扫码人的信息 String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" + "?access_token=%s" + "&openid=%s"; String userInfoUrl = String.format( baseUserInfoUrl, access_token, openid ); //发送请求 String userInfo = HttpClientUtil.doGet(userInfoUrl); //获取返回的userInfo字符串的扫描人信息 JSONObject jsonObject1 = JSON.parseObject(userInfo); System.out.println("------>" + jsonObject1); //昵称 String nickname =(String) jsonObject1.get("nickname"); //头像 String headimgurl =(String) jsonObject1.get("headimgurl"); Integer sex = (Integer) jsonObject1.get("sex"); String unionid = (String) jsonObject1.get("unionid"); WeChatCode weChatCode = new WeChatCode(); weChatCode.setOpenId(openid); weChatCode.setNickName(nickname); weChatCode.setUserPhoto(headimgurl); weChatCode.setUserSex(sex.toString()); weChatCode.setUnid(unionid); weChatCodeDao.save(weChatCode); } //最后返回我们的首页面 //由于我们在前端中需要显示用户名和头像,所以我们需要使用jwt在地址中传递token //不能使用cookie,是因为cookie不能跨域访问,会导致值传递失败 //使用jwt根据member对象生成token字符串 //String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname()); return "redirect:http://localhost:3000?openId="+openid; }catch(Exception e){ return outputEncapsulationObject(PromptMessageEnum.PROCESS_FAIL,"操作失败!",locale); } } /** * 1.生成微信扫描二维码 * @return */ @GetMapping("/weChatScanCodeLogin") public String getWxCode(){ /*第一种方式:固定地址后面拼参数,参数太多,容易拼错 String url = "https://open.weixin.qq.com/connect/qrconnect?appid="+ ConstantWxUtils.WX_OPEN_APP_ID +"&response_type=code"; */ //第二种方式:%s:相当于一个占位符 String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" + "?appid=%s" + "&redirect_uri=%s" + "&response_type=code" + "&scope=snsapi_login" + "&state=%s" + "#wechat_redirect"; //对redirect_url进行URLEnccode编码 String redirect_url =ConstantConfig.WX_OPEN_REDIRECT_URL; try { redirect_url = URLEncoder.encode(redirect_url, "utf-8"); } catch (Exception e) { e.printStackTrace(); } String url =String.format( baseUrl, ConstantConfig.WX_OPEN_APP_ID, redirect_url, "atguigu" ); //请求微信地址 return url; } }