WxController.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. package com.ylx.web.controller.massage;
  2. import cn.binarywang.wx.miniapp.api.WxMaService;
  3. import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
  4. import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
  5. import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
  6. import cn.hutool.core.net.url.UrlBuilder;
  7. import cn.hutool.http.HttpUtil;
  8. import com.alibaba.fastjson.JSON;
  9. import com.alibaba.fastjson2.JSONObject;
  10. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  11. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  12. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  13. import com.ylx.common.annotation.Log;
  14. import com.ylx.common.constant.Constants;
  15. import com.ylx.common.core.controller.BaseController;
  16. import com.ylx.common.core.domain.AjaxResult;
  17. import com.ylx.common.core.domain.R;
  18. import com.ylx.common.core.domain.model.WxLoginUser;
  19. import com.ylx.common.enums.BusinessType;
  20. import com.ylx.framework.web.service.WxTokenService;
  21. import com.ylx.massage.utils.LocationUtil;
  22. import com.ylx.massage.utils.WxQrCodeUtil;
  23. import com.ylx.massage.utils.WxUtil;
  24. import com.ylx.massage.domain.TWxUser;
  25. import com.ylx.massage.service.TWxUserService;
  26. import io.swagger.annotations.Api;
  27. import io.swagger.annotations.ApiOperation;
  28. import lombok.extern.slf4j.Slf4j;
  29. import me.chanjar.weixin.common.error.WxErrorException;
  30. import org.apache.commons.lang3.StringUtils;
  31. import org.springframework.beans.BeanUtils;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.web.bind.annotation.*;
  34. import javax.annotation.Resource;
  35. import java.util.HashMap;
  36. import java.util.List;
  37. import java.util.Map;
  38. /**
  39. * @author : YJR
  40. * @className : WxController
  41. * @description : [描述说明该类的功能]
  42. * @createTime : 2023/6/27 19:44
  43. */
  44. @RestController
  45. @Api(tags = {"微信"})
  46. @RequestMapping("/wx")
  47. @Slf4j
  48. public class WxController extends BaseController {
  49. @Resource
  50. private WxUtil wxUtil;
  51. @Resource
  52. private WxQrCodeUtil wxQrCodeUtil;
  53. @Resource
  54. private TWxUserService wxUserService;
  55. @Resource
  56. private WxTokenService wxTokenService;
  57. @Autowired
  58. private WxMaService wxMaService;
  59. /**
  60. * 获取二维码
  61. *
  62. * @param param
  63. * @return
  64. */
  65. @ApiOperation("获取二维码")
  66. @RequestMapping(value = "getwxQrCode", method = RequestMethod.POST)
  67. public String getWxQrCodeUtil(@RequestBody JSONObject param) {
  68. String cOpenId = param.getString("cOpenId");
  69. return wxQrCodeUtil.getWxQrcode(cOpenId);
  70. }
  71. /**
  72. * 小程序登录
  73. *
  74. * @param wxLoginUser
  75. * @return
  76. */
  77. @PostMapping("v0/login")
  78. @ApiOperation("小程序登录不用")
  79. public AjaxResult login(@RequestBody WxLoginUser wxLoginUser) {
  80. AjaxResult ajax = new AjaxResult();
  81. try {
  82. // 验证输入数据的合法性
  83. if (wxLoginUser == null || wxLoginUser.getCode() == null || wxLoginUser.getCode().isEmpty()) {
  84. return AjaxResult.error("输入数据不合法");
  85. }
  86. //todo 获取用户信息自测方法
  87. WxLoginUser wxUser = wxUtil.getUserOpenId(wxLoginUser.getCode());
  88. if (wxUser == null) {
  89. return AjaxResult.error("获取用户信息失败");
  90. }
  91. // 生成并返回令牌
  92. String token = wxTokenService.createToken(wxUser);
  93. if (token == null || token.isEmpty()) {
  94. return AjaxResult.error("生成令牌失败");
  95. }
  96. ajax.put(Constants.TOKEN, token);
  97. return ajax;
  98. } catch (Exception e) {
  99. // 捕获并处理异常,返回友好的错误信息
  100. JSONObject errorObj = new JSONObject();
  101. errorObj.put("message", "操作失败");
  102. errorObj.put("error", e.getMessage());
  103. return AjaxResult.error(JSON.toJSONString(errorObj));
  104. }
  105. }
  106. /**
  107. * 获取电话号
  108. *
  109. * @param param
  110. * @return
  111. */
  112. @ApiOperation("获取电话号")
  113. @RequestMapping(value = "getPhone", method = RequestMethod.POST)
  114. public R getPhone(@RequestBody JSONObject param) {
  115. String code = param.getString("code");
  116. String openId = param.getString("openId");
  117. if (StringUtils.isBlank(code)) {
  118. return R.fail("openId或者授权conde为空");
  119. }
  120. String phone = wxUtil.getUserPhone(openId, code);
  121. if (StringUtils.isBlank(phone)) {
  122. return R.fail("获取手机号信息失败,请重试");
  123. }
  124. return R.ok(phone);
  125. }
  126. /**
  127. * 获取用户信息
  128. *
  129. * @param
  130. * @return
  131. */
  132. @ApiOperation("获取用户信息")
  133. @RequestMapping(value = "getUserInfo", method = RequestMethod.GET)
  134. public R getUserInfo() {
  135. WxLoginUser wxLoginUser = getWxLoginUser();
  136. // 检查wxLoginUser是否为null
  137. if (wxLoginUser == null) {
  138. return R.fail("用户登录信息不存在");
  139. }
  140. LambdaQueryWrapper<TWxUser> queryWrapper = new LambdaQueryWrapper<TWxUser>()
  141. .eq(TWxUser::getcOpenid, wxLoginUser.getCOpenid());
  142. TWxUser wxUser;
  143. try {
  144. wxUser = wxUserService.getOne(queryWrapper);
  145. } catch (Exception e) {
  146. log.error("获取用户信息失败", e);
  147. return R.fail("获取用户信息失败,系统异常");
  148. }
  149. if (wxUser == null) {
  150. return R.fail("用户信息不存在");
  151. }
  152. // 移除用户登录的session key
  153. wxUser.setcSessionKey(null);
  154. return R.ok(wxUser);
  155. }
  156. /**
  157. * 获取用户信息
  158. *
  159. * @param param
  160. * @return
  161. */
  162. @RequestMapping(value = "getUser", method = RequestMethod.POST)
  163. public List<TWxUser> getUser(@RequestBody JSONObject param) {
  164. QueryWrapper<TWxUser> wrapper = new QueryWrapper<>();
  165. return wxUserService.list(wrapper);
  166. }
  167. @RequestMapping(value = "select", method = RequestMethod.GET)
  168. public R select(Page<TWxUser> page, TWxUser user) {
  169. LambdaQueryWrapper<TWxUser> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
  170. objectLambdaQueryWrapper.eq(StringUtils.isNotBlank(user.getcOpenid()), TWxUser::getcOpenid, user.getcOpenid()).
  171. like(StringUtils.isNotBlank(user.getcNickName()), TWxUser::getcNickName, user.getcNickName());
  172. // 获取查询返回结果
  173. Page<TWxUser> pageSelect = wxUserService.page(page, objectLambdaQueryWrapper);
  174. return R.ok(pageSelect);
  175. }
  176. /**
  177. * 登录接口
  178. */
  179. @ApiOperation("小程序登录")
  180. @Log(title = "小程序登录", businessType = BusinessType.OTHER)
  181. @PostMapping("/login")
  182. public R<Object> login(@RequestParam("code") String code, @RequestParam("encryptedData") String encryptedData,
  183. @RequestParam("iv") String iv) {
  184. try {
  185. // 调用微信 API 获取用户的 openid 和 session_key
  186. WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
  187. String openid = session.getOpenid();
  188. // 调用微信 API 获取用户的手机号
  189. WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNoInfo(session.getSessionKey(), encryptedData, iv);
  190. String phoneNumber = phoneInfo.getPhoneNumber();
  191. // 调用微信 API 获取用户的详细信息
  192. WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(session.getSessionKey(),encryptedData,iv);
  193. // 获取用户昵称
  194. String nickName = userInfo.getNickName();
  195. // 获取用户头像
  196. String avatarUrl = userInfo.getAvatarUrl();
  197. // 获取用户国家
  198. String country = userInfo.getCountry();
  199. // 获取用户省份
  200. String province = userInfo.getProvince();
  201. // 获取用户城市
  202. String city = userInfo.getCity();
  203. // 将用户信息保存到数据库中
  204. LambdaQueryWrapper<TWxUser> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
  205. objectLambdaQueryWrapper.eq(TWxUser::getcOpenid,openid);
  206. TWxUser user = wxUserService.getOne(objectLambdaQueryWrapper);
  207. if (user == null) {
  208. user = new TWxUser();
  209. user.setcOpenid(openid);
  210. user.setcNickName(nickName);
  211. user.setcIcon(avatarUrl);
  212. user.setcPhone(phoneNumber);
  213. wxUserService.save(user);
  214. user.setId(user.getId());
  215. }
  216. WxLoginUser wxUser = new WxLoginUser();
  217. BeanUtils.copyProperties(user, wxUser);
  218. // 生成并返回令牌
  219. String token = wxTokenService.createToken(wxUser);
  220. if (token == null || token.isEmpty()) {
  221. return R.fail("生成令牌失败");
  222. }
  223. wxUser.setToken(token);
  224. // 返回用户信息
  225. return R.ok(wxUser);
  226. } catch (WxErrorException e) {
  227. log.error("登录失败:" + e.getMessage(), e);
  228. return R.fail("登录失败:" + e.getMessage());
  229. }
  230. }
  231. /**
  232. * 更新用户信息接口
  233. */
  234. @PostMapping("/update")
  235. public R updateUserInfo(@RequestBody TWxUser user) {
  236. try {
  237. // 前端校验后,再次进行后端的基础校验
  238. if (user == null || user.getcOpenid() == null || user.getcOpenid().isEmpty()) {
  239. return R.fail("用户信息不能为空");
  240. }
  241. // 保存或更新用户信息
  242. if (wxUserService.saveOrUpdate(user)) {
  243. return R.ok("用户信息更新成功");
  244. } else {
  245. return R.fail("更新用户信息失败");
  246. }
  247. } catch (Exception e) {
  248. // 异常处理,记录日志并返回友好的错误信息
  249. log.error("更新用户信息异常", e);
  250. return R.fail("更新用户信息异常,请稍后尝试");
  251. }
  252. }
  253. /**
  254. * 获取微信用户手机号
  255. *
  256. * @param code code值
  257. */
  258. public String getMobilePhoneByWeixin(String code) {
  259. try {
  260. String accessToken = wxMaService.getAccessToken();
  261. String url = UrlBuilder
  262. .of("https://api.weixin.qq.com/wxa/business/getuserphonenumber")
  263. .addQuery("access_token", accessToken)
  264. .build();
  265. Map<String, Object> paramBody = new HashMap<>(2);
  266. paramBody.put("code", code);
  267. String result = HttpUtil.post(url, JSON.toJSONString(paramBody));
  268. JSONObject jsonObject = JSONObject.from(JSON.parseObject(result));
  269. if ("40029".equals(jsonObject.getString("errcode"))) {
  270. throw new RuntimeException("code无效");
  271. }
  272. if ("-1".equals(jsonObject.getString("errcode"))) {
  273. throw new RuntimeException("微信系统繁忙");
  274. }
  275. JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");
  276. return phoneInfo.getString("phoneNumber");
  277. } catch (WxErrorException e) {
  278. e.printStackTrace();
  279. throw new RuntimeException("获取手机号失败");
  280. }
  281. }
  282. }