package com.cweb.controller; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaUserInfo; import com.alibaba.fastjson.JSONObject; import com.cweb.config.SessionKeyCache; import com.cweb.config.SysConst; import com.cweb.config.WxMaConfiguration; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.hai.common.exception.ErrorCode; import com.hai.common.exception.ErrorHelp; import com.hai.common.exception.SysCode; import com.hai.common.security.*; import com.hai.common.utils.HttpsUtils; import com.hai.common.utils.IDGenerator; import com.hai.common.utils.RedisUtil; import com.hai.common.utils.ResponseMsgUtil; import com.hai.entity.HighUser; import com.hai.model.HighUserModel; import com.hai.model.ResponseData; import com.hai.service.HighUserPayPasswordService; import com.hai.service.HighUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; import java.util.*; @Controller @RequestMapping(value = "/wechat") @Api(value = "微信授权") public class WechatController { private static final Logger log = LoggerFactory.getLogger(WechatController.class); private static final String WX_OPENID_SESSION_REDIS = "WX_OPENID_SESSION_REDIS"; @Autowired private UserCenter userCenter; @Resource private HighUserService highUserService; @Resource private HighUserPayPasswordService highUserPayPasswordService; @Resource private RedisUtil redisUtil; @RequestMapping(value = "/handleCode", method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "小程序code解析") public ResponseData compairCode(@RequestParam(value = "code", required = true) String code, HttpServletRequest request, HttpServletResponse response) { try { //校验code,openId不能同时为空 if (StringUtils.isEmpty(code)) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.REQ_PARAMS_ERROR, ""); } //请求微信api,获取用户session_key以及openId final WxMaService wxService = WxMaConfiguration.getMaService(); WxMaJscode2SessionResult session = wxService.jsCode2SessionInfo(code); //保存小程序用户登录的openId及sessionKey信息 redisUtil.hset(WX_OPENID_SESSION_REDIS, session.getOpenid(), session); JSONObject jo = new JSONObject(); jo.put("openId", session.getOpenid()); return ResponseMsgUtil.success(jo); } catch (Exception e) { return ResponseMsgUtil.exception(e); } } @RequestMapping(value = "/loginByPhone", method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "小程序根据手机号登录或注册") public ResponseData loginByPhone(@RequestParam(value = "encryptedData", required = true) String encryptedData, @RequestParam(value = "iv", required = true) String iv, @RequestParam(value = "openId", required = true) String openId, HttpServletRequest request, HttpServletResponse response) { try { log.error("origin encryptedData:" + encryptedData + ";iv:" + iv); //校验openId不能为空 //encryptedData,iv与unionId不能同时为空 encryptedData = encryptedData.replace(" ", "+"); iv = iv.replace(" ", "+"); log.error("dest encryptedData:" + encryptedData + ";iv:" + iv); if (StringUtils.isEmpty(openId) || StringUtils.isEmpty(encryptedData) || StringUtils.isEmpty(iv)) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.REQ_PARAMS_ERROR, ""); } //请求微信api,获取用户session_key以及openId Object skObject = redisUtil.hget(WX_OPENID_SESSION_REDIS, openId); if (skObject == null) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.WECHAT_LOGIN_ERROR); } WxMaJscode2SessionResult session = (WxMaJscode2SessionResult) skObject; final WxMaService wxService = WxMaConfiguration.getMaService(); WxMaPhoneNumberInfo phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), encryptedData, iv); if (phoneNoInfo == null || StringUtils.isEmpty(phoneNoInfo.getPurePhoneNumber())) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.WECHAT_DECRYPT_ERROR, "用户phoneNumber解析失败"); } // 根据手机号查询用户 HighUser user = highUserService.findByPhone(phoneNoInfo.getPurePhoneNumber()); if (user == null) { user = new HighUser(); user.setName("用户" + IDGenerator.nextId(5)); user.setPhone(phoneNoInfo.getPurePhoneNumber()); user.setRegTime(new Date()); user.setGold(0); user.setOpenId(session.getOpenid()); user.setUnionId(session.getUnionid()); user.setStatus(1); // 用户信息完整状态 // 0:完整 // 1:需要填写用户信息 // 2:需要填写手机号 user.setInfoCompleteStatus(1); highUserService.insertUser(user); } else { if (session.getOpenid() == null) { user.setOpenId(session.getOpenid()); user.setUnionId(session.getUnionid()); highUserService.updateUser(user); } } // 定义个人所有数据 HighUserModel highUserModel = new HighUserModel(); HighUser detailData = highUserService.getDetailDataByUser(user.getId()); detailData.setPassword(null); highUserModel.setHighUser(detailData); SessionObject so = new SessionObject(user.getPhone(), 1, highUserModel); userCenter.save(request, response, so); return ResponseMsgUtil.success(so); } catch (Exception e) { return ResponseMsgUtil.exception(e); } } @RequestMapping(value = "/getUserInfo", method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "小程序获取用户信息") public ResponseData getUserInfo(@RequestParam(value = "encryptedData", required = true) String encryptedData, @RequestParam(value = "iv", required = true) String iv, @RequestParam(value = "openId", required = true) String openId, HttpServletRequest request, HttpServletResponse response) { try { // 用户 SessionObject sessionObject = userCenter.getSessionObject(request); HighUserModel userInfoModel = (HighUserModel) sessionObject.getObject(); //校验openId不能为空 //encryptedData,iv与unionId不能同时为空 encryptedData = encryptedData.replace(" ", "+"); iv = iv.replace(" ", "+"); if (StringUtils.isEmpty(openId) || StringUtils.isEmpty(encryptedData) || StringUtils.isEmpty(iv)) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.REQ_PARAMS_ERROR, ""); } //请求微信api,获取用户session_key以及openId Object skObject = redisUtil.hget(WX_OPENID_SESSION_REDIS, openId); if (skObject == null) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.WECHAT_LOGIN_ERROR); } WxMaJscode2SessionResult session = (WxMaJscode2SessionResult) skObject; final WxMaService wxService = WxMaConfiguration.getMaService(); WxMaUserInfo userInfo = wxService.getUserService().getUserInfo(session.getSessionKey(), encryptedData, iv); if (userInfo == null) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.WECHAT_DECRYPT_ERROR, "用户phoneNumber解析失败"); } HighUser user = highUserService.findByUserId(userInfoModel.getHighUser().getId()); if (user == null) { throw ErrorHelp.genException(SysCode.MiniProgram, ErrorCode.COMMON_ERROR, "未找到用户信息"); } // 用户信息完整状态 // 0:完整 // 1:需要填写用户信息 // 2:需要填写手机号 if (user.getInfoCompleteStatus() == 1) { if (StringUtils.isNotBlank(user.getPhone())) { user.setInfoCompleteStatus(0); } else { user.setInfoCompleteStatus(2); } } user.setName(userInfo.getNickName()); user.setHeaderImg(userInfo.getAvatarUrl()); highUserService.updateUser(user); // 定义个人所有数据 HighUserModel highUserModel = new HighUserModel(); HighUser detailData = highUserService.getDetailDataByUser(user.getId()); detailData.setPassword(null); highUserModel.setHighUser(detailData); if (user.getPhone() == null) { log.error("login error!", "未绑定手机号"); throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未绑定手机号"); } SessionObject so = new SessionObject(user.getPhone(), 1, highUserModel); userCenter.save(request, response, so); return ResponseMsgUtil.success(so); } catch (Exception e) { return ResponseMsgUtil.exception(e); } } @RequestMapping(value = "/getH5AccessToken", method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "【H5】获取AccessToken") public ResponseData getH5AccessToken(@RequestParam(value = "code", required = true) String code) { try { Map params = new HashMap<>(); params.put("appid", SysConst.getSysConfig().getWxH5AppId()); params.put("secret", SysConst.getSysConfig().getWxH5AppSecret()); params.put("code", code); params.put("grant_type", "authorization_code"); return ResponseMsgUtil.success(HttpsUtils.doGet("https://api.weixin.qq.com/sns/oauth2/access_token", params)); } catch (Exception e) { return ResponseMsgUtil.exception(e); } } @RequestMapping(value = "/loginByTel", method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "根据手机号码登陆") public ResponseData loginByTel(@RequestParam(value = "phone", required = true) String phone, @RequestParam(value = "code", required = true) String code, HttpServletRequest request, HttpServletResponse response) { try { // 根据手机号查询用户 HighUser user = highUserService.findByPhone(phone); if (user == null) { user = new HighUser(); user.setName("用户" + IDGenerator.nextId(5)); user.setPhone(phone); user.setRegTime(new Date()); user.setGold(0); user.setStatus(1); // 用户信息完整状态 // 0:完整 // 1:需要填写用户信息 // 2:需要填写手机号 user.setInfoCompleteStatus(1); highUserService.insertUser(user); } // 获取手机号验证码 String phoneSmsCode = (String) redisUtil.get("SMS_"+ phone); // 验证码校验 if (StringUtils.isNotBlank(phoneSmsCode) && Objects.equals(phoneSmsCode,code)) { // 定义个人所有数据 HighUserModel highUserModel = new HighUserModel(); HighUser detailData = highUserService.getDetailDataByUser(user.getId()); detailData.setPassword(null); highUserModel.setHighUser(detailData); SessionObject so = new SessionObject(user.getPhone(), 1, highUserModel); userCenter.save(request, response, so); return ResponseMsgUtil.success(so); } else { throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "验证码错误"); } } catch (Exception e) { return ResponseMsgUtil.exception(e); } } }