package com.ylx.web.controller.massage; 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 cn.hutool.core.io.FileUtil; import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ylx.common.annotation.Log; import com.ylx.common.config.RuoYiConfig; import com.ylx.common.constant.Constants; import com.ylx.common.core.controller.BaseController; import com.ylx.common.core.domain.AjaxResult; import com.ylx.common.core.domain.R; import com.ylx.common.core.domain.model.WxLoginUser; import com.ylx.common.enums.BusinessType; import com.ylx.common.utils.MessageUtils; import com.ylx.common.utils.file.FileUploadUtils; import com.ylx.common.utils.file.FileUtils; import com.ylx.framework.config.ServerConfig; import com.ylx.framework.manager.AsyncManager; import com.ylx.framework.manager.factory.AsyncFactory; import com.ylx.framework.web.service.WxTokenService; import com.ylx.massage.domain.CouponReceive; import com.ylx.massage.domain.vo.TWxUserVo; import com.ylx.massage.service.CouponReceiveService; import com.ylx.massage.service.TCommentService; import com.ylx.massage.service.TbFileService; import com.ylx.massage.utils.LocationUtil; import com.ylx.massage.utils.WxQrCodeUtil; import com.ylx.massage.utils.WxUtil; import com.ylx.massage.domain.TWxUser; import com.ylx.massage.service.TWxUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author : YJR * @className : WxController * @description : [描述说明该类的功能] * @createTime : 2023/6/27 19:44 */ @RestController @Api(tags = {"微信"}) @RequestMapping("/wx") @Slf4j public class WxController extends BaseController { @Resource private WxUtil wxUtil; @Autowired private ServerConfig serverConfig; @Resource private WxQrCodeUtil wxQrCodeUtil; @Resource private TWxUserService wxUserService; @Resource private WxTokenService wxTokenService; @Autowired private WxMaService wxMaService; @Autowired private TbFileService tbFileService; @Autowired private CouponReceiveService couponReceiveService; @Resource(name = "commonAsyncExecutor") private ThreadPoolTaskExecutor threadPoolTaskExecutor; /** * 获取二维码 * * @param inviteUserId * @return AjaxResult */ @ApiOperation("获取二维码") @PostMapping(value="getwxQrCode") public AjaxResult inviteCode(@RequestParam ("inviteUserId")String inviteUserId) throws WxErrorException, IOException { File file = wxMaService.getQrcodeService().createWxaCodeUnlimit(inviteUserId, null, 300, true, null, true); MultipartFile multipartFile = FileUploadUtils.getMultipartFile(file); return tbFileService.uploadFile(multipartFile); } /** * 小程序登录 * * @param wxLoginUser * @return */ @PostMapping("v0/login") @ApiOperation("小程序登录不用") public AjaxResult login(@RequestBody WxLoginUser wxLoginUser) { AjaxResult ajax = new AjaxResult(); try { // 验证输入数据的合法性 if (wxLoginUser == null || wxLoginUser.getCode() == null || wxLoginUser.getCode().isEmpty()) { return AjaxResult.error("输入数据不合法"); } //todo 获取用户信息自测方法 WxLoginUser wxUser = wxUtil.getUserOpenId(wxLoginUser.getCode()); if (wxUser == null) { return AjaxResult.error("获取用户信息失败"); } // 生成并返回令牌 String token = wxTokenService.createToken(wxUser); if (token == null || token.isEmpty()) { return AjaxResult.error("生成令牌失败"); } ajax.put(Constants.TOKEN, token); return ajax; } catch (Exception e) { // 捕获并处理异常,返回友好的错误信息 JSONObject errorObj = new JSONObject(); errorObj.put("message", "操作失败"); errorObj.put("error", e.getMessage()); return AjaxResult.error(JSON.toJSONString(errorObj)); } } /** * 获取电话号 * * @param param * @return */ @ApiOperation("获取电话号") @RequestMapping(value = "getPhone", method = RequestMethod.POST) public R getPhone(@RequestBody JSONObject param) { String code = param.getString("code"); String openId = param.getString("openId"); if (StringUtils.isBlank(code)) { return R.fail("openId或者授权conde为空"); } String phone = wxUtil.getUserPhone(openId, code); if (StringUtils.isBlank(phone)) { return R.fail("获取手机号信息失败,请重试"); } return R.ok(phone); } /** * 获取用户信息 * * @param * @return */ @ApiOperation("获取用户信息") @Log(title = "获取用户信息", businessType = BusinessType.OTHER) @RequestMapping(value = "getUserInfo", method = RequestMethod.GET) public R getUserInfo() { WxLoginUser wxLoginUser = getWxLoginUser(); // 检查wxLoginUser是否为null if (wxLoginUser == null) { return R.fail("用户登录信息不存在"); } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() .eq(TWxUser::getcOpenid, wxLoginUser.getCOpenid()); TWxUser wxUser; try { wxUser = wxUserService.getOne(queryWrapper); } catch (Exception e) { log.error("获取用户信息失败", e); return R.fail("获取用户信息失败,系统异常"); } if (wxUser == null) { return R.fail("用户信息不存在"); } // 移除用户登录的session key wxUser.setcSessionKey(null); return R.ok(wxUser); } /** * 获取用户信息 * * @param param * @return */ @RequestMapping(value = "getUser", method = RequestMethod.POST) public List getUser(@RequestBody JSONObject param) { QueryWrapper wrapper = new QueryWrapper<>(); return wxUserService.list(wrapper); } @RequestMapping(value = "select", method = RequestMethod.GET) public R select(Page page, TWxUser user) { LambdaQueryWrapper objectLambdaQueryWrapper = new LambdaQueryWrapper<>(); objectLambdaQueryWrapper.eq(StringUtils.isNotBlank(user.getcOpenid()), TWxUser::getcOpenid, user.getcOpenid()). like(StringUtils.isNotBlank(user.getcNickName()), TWxUser::getcNickName, user.getcNickName()); // 获取查询返回结果 Page pageSelect = wxUserService.page(page, objectLambdaQueryWrapper); return R.ok(pageSelect); } /** * 登录接口 * @param code * @param encryptedData * @param iv * @param parentOpenId * @return R */ @ApiOperation("小程序登录") @Log(title = "小程序登录", businessType = BusinessType.OTHER) @PostMapping("/login") public R login(@RequestParam("code") String code, @RequestParam("encryptedData") String encryptedData, @RequestParam("iv") String iv, @RequestParam(required = false, value = "parentOpenId") String parentOpenId) { try { // 调用微信 API 获取用户的 openid 和 session_key WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code); String openid = session.getOpenid(); // 调用微信 API 获取用户的手机号 WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNoInfo(session.getSessionKey(), encryptedData, iv); String phoneNumber = phoneInfo.getPhoneNumber(); // 调用微信 API 获取用户的详细信息 WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(session.getSessionKey(), encryptedData, iv); // 获取用户昵称 String nickName = userInfo.getNickName(); // 获取用户头像 String avatarUrl = userInfo.getAvatarUrl(); // 获取用户国家 String country = userInfo.getCountry(); // 获取用户省份 String province = userInfo.getProvince(); // 获取用户城市 String city = userInfo.getCity(); // 将用户信息保存到数据库中 LambdaQueryWrapper objectLambdaQueryWrapper = new LambdaQueryWrapper<>(); objectLambdaQueryWrapper.eq(TWxUser::getcOpenid, openid); TWxUser user = wxUserService.getOne(objectLambdaQueryWrapper); if (user == null) { BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); user = new TWxUser(); user.setcOpenid(openid); user.setcNickName(nickName); user.setcIcon(avatarUrl); user.setcPhone(phoneNumber); user.setCPassword(encoder.encode("123456")) ; wxUserService.save(user); //异步 添加新人优惠卷 TWxUser finalUser = user; // threadPoolTaskExecutor.submit(() -> couponReceiveService.submit(new CouponReceive().setOpenid(finalUser.getcOpenid()).setCouponId("1"))); user.setId(user.getId()); } WxLoginUser wxUser = new WxLoginUser(); BeanUtils.copyProperties(user, wxUser); // 生成并返回令牌 String token = wxTokenService.createToken(wxUser); if (token == null || token.isEmpty()) { return R.fail("生成令牌失败"); } wxUser.setToken(token); // 返回用户信息 // 记录登录信息 AsyncManager.me().execute(AsyncFactory.recordLogininfor(wxUser.getCOpenid(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); return R.ok(wxUser); } catch (WxErrorException e) { log.error("登录失败:" + e.getMessage(), e); return R.fail("登录失败:" + e.getMessage()); } } /** * 更新用户信息接口 */ @PostMapping("/update") public R updateUserInfo(@RequestBody TWxUser user) { try { // 前端校验后,再次进行后端的基础校验 if (user == null || user.getcOpenid() == null || user.getcOpenid().isEmpty()) { return R.fail("用户信息不能为空"); } // 保存或更新用户信息 if (wxUserService.saveOrUpdate(user)) { return R.ok("用户信息更新成功"); } else { return R.fail("更新用户信息失败"); } } catch (Exception e) { // 异常处理,记录日志并返回友好的错误信息 log.error("更新用户信息异常", e); return R.fail("更新用户信息异常,请稍后尝试"); } } /** * 获取微信用户手机号 * * @param code code值 */ public String getMobilePhoneByWeixin(String code) { try { String accessToken = wxMaService.getAccessToken(); String url = UrlBuilder .of("https://api.weixin.qq.com/wxa/business/getuserphonenumber") .addQuery("access_token", accessToken) .build(); Map paramBody = new HashMap<>(2); paramBody.put("code", code); String result = HttpUtil.post(url, JSON.toJSONString(paramBody)); JSONObject jsonObject = JSONObject.from(JSON.parseObject(result)); if ("40029".equals(jsonObject.getString("errcode"))) { throw new RuntimeException("code无效"); } if ("-1".equals(jsonObject.getString("errcode"))) { throw new RuntimeException("微信系统繁忙"); } JSONObject phoneInfo = jsonObject.getJSONObject("phone_info"); return phoneInfo.getString("phoneNumber"); } catch (WxErrorException e) { e.printStackTrace(); throw new RuntimeException("获取手机号失败"); } } /** * 查询微信用户列表 * * @param page 分页参数 * @param user * @return R> 微信用户列表 */ @GetMapping("pc/getUserList") @ApiOperation("查询微信用户列表") public R> getUserList(Page page, TWxUser user) { Page pageSelect = wxUserService.page(page, new LambdaQueryWrapper() .like(StringUtils.isNotBlank(user.getcNickName()), TWxUser::getcNickName, user.getcNickName()) .like(StringUtils.isNotBlank(user.getcPhone()), TWxUser::getcPhone, user.getcPhone()) .orderByDesc(TWxUser::getCreateTime)); return R.ok(pageSelect); } }