From db1d71dfeec6d829cefb4368306c81a60e3acdfe Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Sat, 28 Feb 2026 17:12:16 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=91=E5=B8=81=E4=BB=A3=E7=90=86=E5=85=85?= =?UTF-8?q?=E5=80=BC=E5=92=8C=E8=BD=AC=E8=B4=A6=E9=87=91=E5=B8=81=E5=8F=91?= =?UTF-8?q?=E9=80=81=E7=B3=BB=E7=BB=9F=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/message/OfficialNoticeTypeEnum.java | 10 ++++ .../wallet-application/pom.xml | 4 ++ .../bank/UserBankTransferGoldCmdExe.java | 47 ++++++++++++++++++ .../freight/SendFreightShipCmdExe.java | 49 +++++++++++++++++++ .../salary/SalaryTransferGoldCmdExe.java | 47 ++++++++++++++++++ 5 files changed, 157 insertions(+) diff --git a/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/OfficialNoticeTypeEnum.java b/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/OfficialNoticeTypeEnum.java index 95c6d0e7..b466e710 100644 --- a/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/OfficialNoticeTypeEnum.java +++ b/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/OfficialNoticeTypeEnum.java @@ -257,6 +257,16 @@ public enum OfficialNoticeTypeEnum { */ CP_LOVE_LETTER, + /** + * 用户收到金币 + */ + USER_COINS_RECEIVED, + + /** + * 币商收到金币 + */ + COIN_SELLER_COINS_RECEIVED, + ; diff --git a/rc-service/rc-service-wallet/wallet-application/pom.xml b/rc-service/rc-service-wallet/wallet-application/pom.xml index b950b906..4e81876f 100644 --- a/rc-service/rc-service-wallet/wallet-application/pom.xml +++ b/rc-service/rc-service-wallet/wallet-application/pom.xml @@ -18,6 +18,10 @@ com.red.circle wallet-infrastructure + + com.red.circle + external-inner-api + diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankTransferGoldCmdExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankTransferGoldCmdExe.java index 4d78c90a..233d3790 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankTransferGoldCmdExe.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/bank/UserBankTransferGoldCmdExe.java @@ -4,16 +4,22 @@ import com.red.circle.common.business.core.enums.OpUserType; import com.red.circle.common.business.core.enums.ReceiptType; import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; import com.red.circle.component.redis.service.RedisService; +import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient; +import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateCustomizeCmd; +import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum; import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.framework.core.response.ResponseErrorCode; +import com.red.circle.framework.dto.ResultResponse; import com.red.circle.order.inner.endpoint.UserFreightRechargeRecordClient; import com.red.circle.order.inner.endpoint.UserRechargeCountClient; import com.red.circle.other.inner.endpoint.team.target.TeamMemberClient; import com.red.circle.other.inner.endpoint.team.target.UserBillDiamondBalanceClient; import com.red.circle.other.inner.endpoint.user.region.UserRegionClient; +import com.red.circle.other.inner.endpoint.user.user.UserProfileClient; import com.red.circle.other.inner.endpoint.user.user.UserSvipClient; import com.red.circle.other.inner.model.dto.user.SysExchangeGoldTipDTO; +import com.red.circle.other.inner.model.dto.user.UserProfileDTO; import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.num.ArithmeticUtils; import com.red.circle.tool.core.sequence.IdWorkerUtils; @@ -42,6 +48,7 @@ import com.red.circle.wallet.inner.model.enums.FreightBalanceOrigin; import com.red.circle.wallet.inner.model.enums.GoldOrigin; import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent; import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Component; import java.math.BigDecimal; @@ -67,6 +74,8 @@ public class UserBankTransferGoldCmdExe { private final FreightBalanceService freightBalanceService; private final UserRegionClient userRegionClient; private final FreightBalanceRunningWaterService freightBalanceRunningWaterService; + private final OfficialNoticeClient officialNoticeClient; + private final UserProfileClient userProfileClient; /** * 执行转账到金币操作 @@ -160,6 +169,15 @@ public class UserBankTransferGoldCmdExe { .setOrigin(FreightBalanceOrigin.PURCHASE.name()) .setRemark(remark) .withCreateUser(cmd.getReqUserId())); + + String noticeContent = getNoticeContent(cmd, goldQuantity); + officialNoticeClient.send( + NoticeExtTemplateCustomizeCmd.builder() + .toAccount(cmd.getAcceptUserId()) + .noticeType(OfficialNoticeTypeEnum.COIN_SELLER_COINS_RECEIVED) + .content(noticeContent) + .build() + ); return; } @@ -178,6 +196,35 @@ public class UserBankTransferGoldCmdExe { ); } + private String getNoticeContent(UserBankWithdrawTransferCmd cmd, BigDecimal goldQuantity) { + // 获取发送者(代理)的 account + String agencyAccount = resolveAccount(cmd.getReqUserId()); + + // 获取接收者的区域判断是否为阿拉伯语 + ResultResponse regionResponse = userRegionClient.getRegionCode(cmd.getAcceptUserId()); + boolean arRegion = regionResponse.checkSuccess() && "AR".equals(regionResponse.getBody()); + + long goldCoins = goldQuantity.longValue(); + String noticeTemplate = arRegion + ? "لقد استلمت %,d عملة. تم تحويل الأموال من المستخدم (ID: %s) إلى محفظة وكالة الشحن الخاصة بك. يرجى تأكيد الاستلام." + : "You have received %,d Coins. The funds have been transferred from user (ID: %s) to your recharge agency wallet. Please confirm receipt."; + return String.format(noticeTemplate, goldCoins, agencyAccount); + } + + /** + * 获取用户展示的 account,优先取专属号(ownSpecialId),否则取普通 account + */ + private String resolveAccount(Long userId) { + ResultResponse response = userProfileClient.getByUserId(userId); + if (!response.checkSuccess() || response.getBody() == null) { + return Objects.toString(userId); + } + UserProfileDTO profile = response.getBody(); + return profile.getOwnSpecialId() != null + ? profile.getOwnSpecialId().getAccount() + : profile.getAccount(); + } + /** * 获得1$兑换多少金币比例, 基于区域+用户输入的美元. * diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/freight/SendFreightShipCmdExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/freight/SendFreightShipCmdExe.java index 23231b2a..b8f13ea7 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/freight/SendFreightShipCmdExe.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/freight/SendFreightShipCmdExe.java @@ -7,6 +7,9 @@ import com.red.circle.common.business.enums.IncomeExpenditureEnum; import com.red.circle.common.business.enums.SendPropsOrigin; import com.red.circle.component.mq.MessageEventProcess; import com.red.circle.component.redis.service.RedisService; +import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient; +import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateCustomizeCmd; +import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum; import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.framework.dto.ResultResponse; @@ -18,6 +21,7 @@ import com.red.circle.other.inner.endpoint.activity.AppRankCountClient; import com.red.circle.other.inner.endpoint.activity.CumulativeRechargeClient; import com.red.circle.other.inner.endpoint.activity.PropsActivityClient; import com.red.circle.other.inner.endpoint.sys.EnumConfigClient; +import com.red.circle.other.inner.endpoint.user.region.UserRegionClient; import com.red.circle.other.inner.endpoint.user.user.*; import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum; import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd; @@ -30,6 +34,7 @@ import com.red.circle.tool.core.num.ArithmeticUtils; import com.red.circle.tool.core.tuple.PennyAmount; import com.red.circle.other.inner.asserts.user.UserErrorCode; import com.red.circle.wallet.app.dto.cmd.FreightShipSendCmd; +import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; import com.red.circle.wallet.domain.gateway.FreightShipGateway; import com.red.circle.wallet.domain.gateway.WalletGoldGateway; import com.red.circle.wallet.domain.wallet.WalletReceipt; @@ -85,6 +90,8 @@ public class SendFreightShipCmdExe { private final PropsActivityClient propsActivityClient; private final UserOneTimeTaskClient userOneTimeTaskClient; private final InviteUserClient inviteUserClient; + private final UserRegionClient userRegionClient; + private final OfficialNoticeClient officialNoticeClient; public BigDecimal execute(FreightShipSendCmd cmd) { @@ -135,6 +142,19 @@ public class SendFreightShipCmdExe { .setCreateTime(cmd.reqTimeElseNow()) ); + try { + String noticeContent = getNoticeContent(cmd, cmd.getQuantity()); + officialNoticeClient.send( + NoticeExtTemplateCustomizeCmd.builder() + .toAccount(cmd.getAcceptUserId()) + .noticeType(OfficialNoticeTypeEnum.USER_COINS_RECEIVED) + .content(noticeContent) + .build() + ); + } catch (Exception e) { + log.error("send freight balance failed: {}", e.getMessage()); + } + // 累计充值 incrRechargeQuantity(cmd); @@ -159,6 +179,35 @@ public class SendFreightShipCmdExe { } } + private String getNoticeContent(FreightShipSendCmd cmd, BigDecimal goldQuantity) { + // 获取发送者(代理)的 account + String agencyAccount = resolveAccount(cmd.getReqUserId()); + + // 获取接收者的区域判断是否为阿拉伯语 + ResultResponse regionResponse = userRegionClient.getRegionCode(cmd.getAcceptUserId()); + boolean arRegion = regionResponse.checkSuccess() && "AR".equals(regionResponse.getBody()); + + long goldCoins = goldQuantity.longValue(); + String noticeTemplate = arRegion + ? "تم الشحن بنجاح! قام وكيل الشحن (ID: %s) بشحن %,d عملة إلى حسابك. يرجى تأكيد الاستلام." + : "Recharge successful! recharge agency (ID: %s) has recharged %,d Coins to your account. Please confirm receipt."; + return String.format(noticeTemplate, agencyAccount, goldCoins); + } + + /** + * 获取用户展示的 account,优先取专属号(ownSpecialId),否则取普通 account + */ + private String resolveAccount(Long userId) { + ResultResponse response = userProfileClient.getByUserId(userId); + if (!response.checkSuccess() || response.getBody() == null) { + return Objects.toString(userId); + } + UserProfileDTO profile = response.getBody(); + return profile.getOwnSpecialId() != null + ? profile.getOwnSpecialId().getAccount() + : profile.getAccount(); + } + private void completedFirstCharge(Long userId, String sysOrigin) { UserProfileDTO userProfileDTO = userProfileClient.getByUserId(userId).getBody(); Duration duration = Duration.between(userProfileDTO.getCreateTime().toLocalDateTime(), LocalDateTime.now()); diff --git a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java index 7d2d03ff..8ec917f1 100644 --- a/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java +++ b/rc-service/rc-service-wallet/wallet-application/src/main/java/com/red/circle/wallet/app/command/salary/SalaryTransferGoldCmdExe.java @@ -4,17 +4,24 @@ import com.red.circle.common.business.core.enums.OpUserType; import com.red.circle.common.business.core.enums.ReceiptType; import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; import com.red.circle.component.redis.service.RedisService; +import com.red.circle.external.inner.endpoint.message.OfficialNoticeClient; +import com.red.circle.external.inner.model.cmd.message.notice.official.NoticeExtTemplateCustomizeCmd; +import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum; import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.response.CommonErrorCode; import com.red.circle.framework.core.response.ResponseErrorCode; +import com.red.circle.framework.dto.ResultResponse; import com.red.circle.other.inner.endpoint.user.region.UserRegionClient; +import com.red.circle.other.inner.endpoint.user.user.UserProfileClient; import com.red.circle.other.inner.model.dto.user.SysExchangeGoldTipDTO; +import com.red.circle.other.inner.model.dto.user.UserProfileDTO; import com.red.circle.tool.core.num.ArithmeticUtils; import com.red.circle.tool.core.sequence.IdWorkerUtils; import com.red.circle.tool.core.tuple.PennyAmount; import com.red.circle.wallet.app.convertor.SalaryAccountConvertor; import com.red.circle.wallet.app.dto.clientobject.UserBankWithdrawResultCO; import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd; +import com.red.circle.wallet.app.dto.cmd.UserBankWithdrawTransferCmd; import com.red.circle.wallet.domain.gateway.SalaryAccountGateway; import com.red.circle.wallet.domain.gateway.WalletGoldGateway; import com.red.circle.wallet.domain.salary.SalaryReceipt; @@ -59,6 +66,8 @@ public class SalaryTransferGoldCmdExe { private final FreightBalanceRunningWaterService freightBalanceRunningWaterService; private final SalaryAccountGateway salaryAccountGateway; private final SalaryAccountConvertor salaryAccountConvertor; + private final UserProfileClient userProfileClient; + private final OfficialNoticeClient officialNoticeClient; /** * 执行转账到金币操作 @@ -133,6 +142,15 @@ public class SalaryTransferGoldCmdExe { .setOrigin(FreightBalanceOrigin.PURCHASE.name()) .setRemark(remark) .withCreateUser(cmd.getReqUserId())); + + String noticeContent = getNoticeContent(cmd, goldQuantity); + officialNoticeClient.send( + NoticeExtTemplateCustomizeCmd.builder() + .toAccount(cmd.getAcceptUserId()) + .noticeType(OfficialNoticeTypeEnum.COIN_SELLER_COINS_RECEIVED) + .content(noticeContent) + .build() + ); return; } @@ -151,6 +169,35 @@ public class SalaryTransferGoldCmdExe { ); } + private String getNoticeContent(SalaryWithdrawCmd cmd, BigDecimal goldQuantity) { + // 获取发送者(代理)的 account + String agencyAccount = resolveAccount(cmd.getReqUserId()); + + // 获取接收者的区域判断是否为阿拉伯语 + ResultResponse regionResponse = userRegionClient.getRegionCode(cmd.getAcceptUserId()); + boolean arRegion = regionResponse.checkSuccess() && "AR".equals(regionResponse.getBody()); + + long goldCoins = goldQuantity.longValue(); + String noticeTemplate = arRegion + ? "لقد استلمت %,d عملة. تم تحويل الأموال من المستخدم (ID: %s) إلى محفظة وكالة الشحن الخاصة بك. يرجى تأكيد الاستلام." + : "You have received %,d Coins. The funds have been transferred from user (ID: %s) to your recharge agency wallet. Please confirm receipt."; + return String.format(noticeTemplate, goldCoins, agencyAccount); + } + + /** + * 获取用户展示的 account,优先取专属号(ownSpecialId),否则取普通 account + */ + private String resolveAccount(Long userId) { + ResultResponse response = userProfileClient.getByUserId(userId); + if (!response.checkSuccess() || response.getBody() == null) { + return Objects.toString(userId); + } + UserProfileDTO profile = response.getBody(); + return profile.getOwnSpecialId() != null + ? profile.getOwnSpecialId().getAccount() + : profile.getAccount(); + } + /** * 获得1$兑换多少金币比例, 基于区域+用户输入的美元. *