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$兑换多少金币比例, 基于区域+用户输入的美元.
*