diff --git a/ruoyi-admin/src/main/java/org/dromara/app/AppMemberController.java b/ruoyi-admin/src/main/java/org/dromara/app/AppMemberController.java index 40af9e7cf..58e3f4dd6 100644 --- a/ruoyi-admin/src/main/java/org/dromara/app/AppMemberController.java +++ b/ruoyi-admin/src/main/java/org/dromara/app/AppMemberController.java @@ -25,11 +25,14 @@ import com.wzj.soopin.transaction.convert.WithdrawConvert; import com.wzj.soopin.transaction.domain.bo.ChargeBO; import com.wzj.soopin.transaction.domain.bo.WithdrawBO; import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferResponseNew; +import com.wzj.soopin.transaction.domain.entity.WxAuthResponse; import com.wzj.soopin.transaction.domain.po.Withdraw; import com.wzj.soopin.transaction.enums.WithdrawType; import com.wzj.soopin.transaction.service.IAccountBillService; import com.wzj.soopin.transaction.service.IChargeService; import com.wzj.soopin.transaction.service.IWithdrawService; +import com.wzj.soopin.transaction.service.impl.WxAuthService; +import com.wzj.soopin.transaction.service.impl.WxPayService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -79,6 +82,8 @@ public class AppMemberController { private final IWithdrawService withdrawService; private final WithdrawConvert withdrawConvert; + private final WxAuthService wxAuthService; + @Operation(summary = "获取会员账户信息详细信息") @GetMapping(value = "/info") public R getInfo(Long memberId) { @@ -158,7 +163,7 @@ public class AppMemberController { throw new ServiceException("用户未登录"); } Long memberId = loginUser.getUserId(); - +// ValidatorUtils.validate(loginBody); AuthResponse response = SocialUtils.loginAuth( loginBody.getSource(), loginBody.getSocialCode(), @@ -169,8 +174,9 @@ public class AppMemberController { AuthUser authUserData = response.getData(); - String unionId=authUserData.getToken().getUnionId(); - Member member = Member.builder().id(memberId).openId(unionId).build(); +// WxAuthResponse response1 = wxAuthService.getAccessTokenByCode(loginBody.getSocialCode()); +// String OpenId=response1.getOpenid(); + Member member = Member.builder().id(memberId).openId(authUserData.getUuid()).build(); service.updateById(member); // 更新用户的微信信息 // 返回给前端 diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 7d86da8d9..1890b04a0 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -272,7 +272,7 @@ wechat: private-key-path: "classpath:cert/apiclient_key.pem" # 商户私钥文件路径 transfer-notify-url: https://wuzhongjie.com.cn/prod-api/api/transfer/callback # 转账回调地址 app-id: wxebcdaea31881caab # 应用ID - secret: your_wechat_secret # 应用密钥 + secret: 86fbcab880e4066ac5c75af6f4f003c2 # 应用密钥 mini-program: # app-id: wx87a5db19138da60d # secret: 856ca8bae38ccaecc1353c9abedf6b41 diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 49f7d0188..b68f568ad 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -272,7 +272,7 @@ wechat: private-key-path: "/java/cert/apiclient_key.pem" # 商户私钥文件路径 transfer-notify-url: https://wuzhongjie.com.cn/prod-api/api/transfer/callback # 转账回调地址 app-id: wxebcdaea31881caab # 应用ID - secret: your_wechat_secret # 应用密钥 + secret: 71826d76bad096ec5407897c6ed1391f # 应用密钥 mini-program: # app-id: wx87a5db19138da60d # secret: 856ca8bae38ccaecc1353c9abedf6b41 diff --git a/ruoyi-common/ruoyi-common-mq/src/main/java/org/dromara/common/mq/domain/MQMessage.java b/ruoyi-common/ruoyi-common-mq/src/main/java/org/dromara/common/mq/domain/MQMessage.java index b057c77cf..66fe401d9 100644 --- a/ruoyi-common/ruoyi-common-mq/src/main/java/org/dromara/common/mq/domain/MQMessage.java +++ b/ruoyi-common/ruoyi-common-mq/src/main/java/org/dromara/common/mq/domain/MQMessage.java @@ -29,8 +29,7 @@ public class MQMessage { /** * 消息类型 */ - private MQMessageType - messageType; + private String messageType; /** * 消息内容 */ diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/CommentServiceImpl.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/CommentServiceImpl.java index c7beab3ef..07558e23e 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/CommentServiceImpl.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/CommentServiceImpl.java @@ -405,7 +405,7 @@ public class CommentServiceImpl extends ServiceImpl impl MQMessage mqMessage = new MQMessage(); mqMessage.setTag(MessageActionEnum.INTERACTION_COMMENT.name()); - mqMessage.setMessageType(MQMessageType.IM); + mqMessage.setMessageType(MQMessageType.IM.name()); if (bo.getFatherCommentId() == 0L) { // 评论视频,通知视频作者 if ( !String.valueOf(loginUser.getUserId()).equals(bo.getVlogerId())) { diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogPushServiceImpl.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogPushServiceImpl.java index 2ed862704..8481f4103 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogPushServiceImpl.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogPushServiceImpl.java @@ -76,7 +76,7 @@ public class VlogPushServiceImpl implements IVlogPushService { MQMessage message = MQMessage.builder() .topic("MEMBER_VLOG_MSG") .tag(HOT_VLOG_TAG) - .messageType(MQMessageType.VLOG) + .messageType(MQMessageType.VLOG.name()) .data(vlogId) .source("vlog_service") .sendTime(LocalDateTime.now()) @@ -94,7 +94,7 @@ public class VlogPushServiceImpl implements IVlogPushService { MQMessage message = MQMessage.builder() .topic("MEMBER_VLOG_MSG") .tag(tag) - .messageType(MQMessageType.VLOG) + .messageType(MQMessageType.VLOG.name()) .data(vlogId) .source("vlog_service") .sendTime(LocalDateTime.now()) diff --git a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java index 6abbdcd77..f1345e91d 100644 --- a/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java +++ b/ruoyi-modules/ruoyi-content/src/main/java/com/wzj/soopin/content/service/impl/VlogServiceImpl.java @@ -151,7 +151,7 @@ public class VlogServiceImpl extends ServiceImpl implements Vl //发出mq消息,异步处理上传 MQMessage message = MQMessage.builder() - .messageType(MQMessageType.VLOG) + .messageType(MQMessageType.VLOG.name()) .data(vlog.getId()) .source("app") .topic("VLOG_UPLOAD_TOPIC") @@ -330,7 +330,7 @@ public class VlogServiceImpl extends ServiceImpl implements Vl params.put("vlogId",vlog.getId()); params.put("firstFrameImg",vlog.getFirstFrameImg()); MQMessage mqMessage = new MQMessage(); - mqMessage.setMessageType(MQMessageType.IM); + mqMessage.setMessageType(MQMessageType.IM.name()); mqMessage.setTag(MessageActionEnum.INTERACTION_LIKE.name()); mqMessage.setToUserId(Long.valueOf(vlog.getMemberId())); mqMessage.setData(params); diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java index 496df2090..da9b96e49 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FansServiceImpl.java @@ -87,7 +87,7 @@ public class FansServiceImpl extends ServiceImpl implements IF params.put("nickname", follower.getNickname() == null ? "" : follower.getNickname()); params.put("faceUrl", vlogger.getAvatar() ); MQMessage message = MQMessage.builder() - .messageType(MQMessageType.IM) + .messageType(MQMessageType.IM.name()) .data(params) .tag(MessageActionEnum.NEW_FOUCS.name()) .toUserId(vlogger.getId()) diff --git a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FeedbackServiceImpl.java b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FeedbackServiceImpl.java index b804f93a2..03b3af5bf 100644 --- a/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FeedbackServiceImpl.java +++ b/ruoyi-modules/ruoyi-member/src/main/java/com/wzj/soopin/member/service/impl/FeedbackServiceImpl.java @@ -115,7 +115,7 @@ public class FeedbackServiceImpl extends ServiceImpl i params.put("faceUrl", loginUser.getAvatar() ); MQMessage mqMessage = new MQMessage(); - mqMessage.setMessageType(MQMessageType.IM); + mqMessage.setMessageType(MQMessageType.IM.name()); mqMessage.setTag(MessageActionEnum.INTERACTION_LIKE.name()); mqMessage.setToUserId(aim.getMemberId()); mqMessage.setData(params); diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/wzj/soopin/order/service/impl/AftersaleServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/wzj/soopin/order/service/impl/AftersaleServiceImpl.java index 7a48e4638..8bc821876 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/wzj/soopin/order/service/impl/AftersaleServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/wzj/soopin/order/service/impl/AftersaleServiceImpl.java @@ -250,7 +250,7 @@ public class AftersaleServiceImpl extends ServiceImpl implements params.put("account", MessageActionEnum.ORDER_PAY.getAccount()); MQMessage mqMessage = new MQMessage(); mqMessage.setTag(MessageActionEnum.ORDER_PAY.name()); - mqMessage.setMessageType(MQMessageType.IM); + mqMessage.setMessageType(MQMessageType.IM.name()); mqMessage.setToUserId(order.getMemberId()); mqMessage.setData(params); MqUtil.sendIMMessage(mqMessage); diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WxPayController.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WxPayController.java index b8c4ae645..bc798ee25 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WxPayController.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/controller/WxPayController.java @@ -182,7 +182,7 @@ public class WxPayController { }) public ResponseEntity getOpenId(@RequestParam String code) { try { - WxAuthResponse response = wxAuthService.getOpenIdByCode(code); + WxAuthResponse response = wxAuthService.getAccessTokenByCode(code); return new ResponseEntity<>(response, HttpStatus.OK); } catch (Exception e) { log.error("获取openid时发生异常: {}", e.getMessage()); diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/domain/entity/WxAuthResponse.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/domain/entity/WxAuthResponse.java index 016a05b3e..1c016349b 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/domain/entity/WxAuthResponse.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/domain/entity/WxAuthResponse.java @@ -13,4 +13,9 @@ public class WxAuthResponse { private String unionid; private String errcode; private String errmsg; + private String access_token; + private String expires_in; + private String refresh_token; + private String scope; + } diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/ChargeServiceImpl.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/ChargeServiceImpl.java index 2f4fd8183..f613791a4 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/ChargeServiceImpl.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/ChargeServiceImpl.java @@ -62,7 +62,7 @@ public class ChargeServiceImpl extends ServiceImpl impleme Map params = new HashMap<>(); MQMessage mqMessage = new MQMessage(); mqMessage.setTag(MessageActionEnum.ORDER_RECHARGE.name()); - mqMessage.setMessageType(MQMessageType.IM); + mqMessage.setMessageType(MQMessageType.IM.name()); // 评论视频,通知视频作者 params.put("orderID", charge.getId()); params.put("amount", charge.getMoney()); diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/EasypayServiceImpl.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/EasypayServiceImpl.java index cf45efa3f..25052d2e8 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/EasypayServiceImpl.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/EasypayServiceImpl.java @@ -547,7 +547,7 @@ public class EasypayServiceImpl implements IEasypayService { } MQMessage mqMessage = new MQMessage(); mqMessage.setTag(MessageActionEnum.ORDER_PAY.name()); - mqMessage.setMessageType(MQMessageType.IM); + mqMessage.setMessageType(MQMessageType.IM.name()); mqMessage.setToUserId(order.getMemberId()); mqMessage.setData(params); return mqMessage; diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java index da784522c..d1668fc2a 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WithdrawServiceImpl.java @@ -182,21 +182,9 @@ public class WithdrawServiceImpl extends ServiceImpl i withdraw.setCode(SnowFlake.createStr("TX")); save(withdraw); - BigDecimal newBalance = balance.subtract(withdraw.getMoney()); - //锁定用户余额 - memberAccountService.updateById(memberAccount.toBuilder().wallet(newBalance).build()); - //生成账单 - AccountBill memberAccountChangeRecord = AccountBill.builder() - .accountId(withdraw.getMemberId()) - .moneyBalance(newBalance) - .beforeBalance(balance) - .afterBalance(newBalance) - .changeType(AccountBillChangeTypeEnum.OUT.getCode()) - .changeDesc("提现锁定") - .source(AccountBillSourceEnum.WITHDRAW.getCode()) - .build(); - accountBillService.save(memberAccountChangeRecord); + accountBillService.reduceMoney(withdraw.getMoney(),withdraw.getMemberId(),AccountBillSourceEnum.WITHDRAW,""); + InitiateBatchTransferResponseNew response = null; try{ diff --git a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WxAuthService.java b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WxAuthService.java index b32da2222..a69680dea 100644 --- a/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WxAuthService.java +++ b/ruoyi-modules/ruoyi-transaction/src/main/java/com/wzj/soopin/transaction/service/impl/WxAuthService.java @@ -2,17 +2,31 @@ package com.wzj.soopin.transaction.service.impl; import cn.hutool.core.lang.Assert; import cn.hutool.core.text.StrBuilder; -import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpRequest; import com.alibaba.fastjson2.JSONObject; -import com.wzj.soopin.transaction.domain.entity.WxAuthResponse; import com.wzj.soopin.transaction.config.WechatMiniProgramConfig; +import com.wzj.soopin.transaction.domain.entity.WxAuthResponse; import com.wzj.soopin.transaction.wechat.WechatPayConfig; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.exception.ServiceException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import org.springframework.web.client.RestTemplate; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.wzj.soopin.transaction.domain.entity.WxAuthResponse; @Service @Slf4j @@ -26,23 +40,110 @@ public class WxAuthService { private RestTemplate restTemplate = new RestTemplate(); + + // Jackson 解析器(Spring 默认注入,替代 fastjson,减少第三方依赖) + @Autowired + private ObjectMapper objectMapper; + /** - * 网页-通过code获取openid - * - * @param code 授权码 - * @return 包含openid的响应对象 + * 通过 code 换取 OAuth2 access_token(优化后) + * @param code 授权回调返回的 code + * @return WxAuthResponse 解析后的响应 */ - public WxAuthResponse getOpenIdByCode(String code) { + public WxAuthResponse getAccessTokenByCode(String code) { + // 1. 核心:参数校验(解决 41002 错误的根本) + validateParams(code); + + // 2. 拼接 URL(脱敏日志,避免泄露 secret) + String appId = wechatPayConfig.getAppId(); + String secret = wechatPayConfig.getSecret(); String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"; - url = String.format(url, wechatPayConfig.getAppId(), wechatPayConfig.getSecret(), code); - WxAuthResponse response = restTemplate.getForObject(url, WxAuthResponse.class); - log.info("获取openid结果: {}", response); - log.info("AppId为: {}", wechatPayConfig.getAppId()); - log.info("Secret为: {}", wechatPayConfig.getSecret()); - if (response == null || response.getOpenid() == null) { - throw new RuntimeException("Failed to get openid from WeChat"); + // 格式化 URL + String requestUrl = String.format( + url, + appId, + secret, + code + ); + + log.info("调用微信 OAuth2 access_token 接口,脱敏URL:{}", requestUrl); + + // 3. 发起 HTTP GET 请求(设置请求头,模拟浏览器,避免被拦截) + HttpHeaders headers = new HttpHeaders(); + headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"); + HttpEntity requestEntity = new HttpEntity<>(headers); + try { + // 发起请求(RestTemplate 自动处理 URL 编码,避免特殊字符问题) + ResponseEntity responseEntity = restTemplate.exchange( + requestUrl, + HttpMethod.GET, + requestEntity, + String.class + ); + + // 4. 校验响应状态码(非 200 直接抛异常) + if (!responseEntity.getStatusCode().is2xxSuccessful()) { + throw new ServiceException( + ); + } + String responseBody = responseEntity.getBody(); + log.info("微信 OAuth2 接口响应内容:{}", responseBody); + + // 5. JSON 解析(用 Jackson 替代 fastjson,与 Spring 生态兼容,且异常可控) + try { + return objectMapper.readValue(responseBody, WxAuthResponse.class); + } catch (Exception e) { + throw new ServiceException( + ); + } + + } catch (ServiceException e) { + // 捕获 HTTP 相关异常(连接超时、读取超时等) + throw new ServiceException( + "OAuth 接口 HTTP 请求失败" + ); + } catch (Exception e) { + // 捕获其他未知异常(兜底处理) + throw new ServiceException( + "获取 OAuth access_token 未知异常" + ); } - return response; + } + + /** + * 1. 参数校验(解决 appid/secret/code 缺失问题) + */ + private void validateParams(String code) { + String appId = wechatMiniProgramConfig.getAppId(); + String secret = wechatMiniProgramConfig.getSecret(); + + // 校验 appid(非 null、非空字符串、非空白) + if (!StringUtils.hasText(appId)) { + throw new ServiceException("微信 OAuth 配置异常:appid 缺失(null/空字符串)"); + } + // 校验 secret + if (!StringUtils.hasText(secret)) { + throw new ServiceException("微信 OAuth 配置异常:secret 缺失(null/空字符串)"); + } + // 校验 code(授权回调返回的 code 不能为空) + if (!StringUtils.hasText(code)) { + throw new ServiceException("微信 OAuth 授权异常:code 缺失(null/空字符串)"); + } + } + + /** + * 2. 敏感信息脱敏(避免 secret 明文打印,符合安全规范) + * 示例:secret=abcdefghijklmn → 脱敏后=abcdef****mn + */ + private String maskSensitiveInfo(String sensitiveStr) { + if (!StringUtils.hasText(sensitiveStr)) { + return ""; + } + int length = sensitiveStr.length(); + if (length <= 6) { + return sensitiveStr.substring(0, 2) + "****"; // 短字符串特殊处理 + } + return sensitiveStr.substring(0, 6) + "****" + sensitiveStr.substring(length - 2); } /**