feat: update mifapay and region config flows
This commit is contained in:
parent
f7d821ae37
commit
2fd0976d0d
@ -34,8 +34,8 @@ red-circle:
|
||||
access-url: ${LIKEI_TENCENT_COS_ACCESS_URL}
|
||||
instant-message:
|
||||
broadcast-group:
|
||||
LOTFUN: ${LIKEI_IM_BROADCAST_GROUP_LOTFUN}
|
||||
LIKEI: ${LIKEI_IM_BROADCAST_GROUP_LIKEI}
|
||||
LOTFUN: "${LIKEI_IM_BROADCAST_GROUP_LOTFUN}"
|
||||
LIKEI: "${LIKEI_IM_BROADCAST_GROUP_LIKEI}"
|
||||
tencet-trtc:
|
||||
secretId: ${LIKEI_TRTC_SECRET_ID}
|
||||
secretKey: ${LIKEI_TRTC_SECRET_KEY}
|
||||
|
||||
@ -52,6 +52,7 @@ red-circle:
|
||||
gateway-base-url: ${LIKEI_MIFA_PAY_GATEWAY_BASE_URL}
|
||||
rsa-private-key: ${LIKEI_MIFA_PAY_RSA_PRIVATE_KEY}
|
||||
platform-rsa-public-key: ${LIKEI_MIFA_PAY_PLATFORM_RSA_PUBLIC_KEY}
|
||||
notify-url: ${LIKEI_MIFA_PAY_NOTIFY_URL:https://jvapi.haiyihy.com/play-server-notice/mifa_pay/receive_payment}
|
||||
|
||||
airwallex:
|
||||
client-id: ${LIKEI_AIRWALLEX_CLIENT_ID}
|
||||
|
||||
@ -114,7 +114,7 @@ activity:
|
||||
|
||||
|
||||
scheduler:
|
||||
room-empty-clean: false
|
||||
room-online-quantity-reconcile: true
|
||||
room-red-packet-expire: false
|
||||
game-king-reward: false
|
||||
noble-daily-reward: false
|
||||
|
||||
@ -0,0 +1,119 @@
|
||||
package com.red.circle.common.business.core.util;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.red.circle.tool.core.json.JacksonUtils;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 国家码别名工具.
|
||||
*/
|
||||
public final class CountryCodeAliasUtils {
|
||||
|
||||
private static final String SA = "SA";
|
||||
private static final String KSA = "KSA";
|
||||
|
||||
private CountryCodeAliasUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化国家码.
|
||||
*/
|
||||
public static String normalize(String code) {
|
||||
return StringUtils.isBlank(code) ? null : code.trim().toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 沙特兼容归一化,保留非沙特国家原有写法.
|
||||
*/
|
||||
public static String normalizeSaudiCode(String code) {
|
||||
String normalized = normalize(code);
|
||||
return isSaudiCode(normalized) ? SA : normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是沙特国家码.
|
||||
*/
|
||||
public static boolean isSaudiCode(String code) {
|
||||
String normalized = normalize(code);
|
||||
return SA.equals(normalized) || KSA.equals(normalized);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取国家码别名集合.
|
||||
*/
|
||||
public static Set<String> legacyAliases(String code) {
|
||||
return buildMatchCodes(code, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析存储中的别名数组.
|
||||
*/
|
||||
public static List<String> parseAliasCodes(String aliasCodes) {
|
||||
if (StringUtils.isBlank(aliasCodes)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
try {
|
||||
List<String> values = JacksonUtils.readValue(aliasCodes, new TypeReference<List<String>>() {});
|
||||
return normalizeCodes(values);
|
||||
} catch (Exception ignore) {
|
||||
return normalizeCodes(List.of(aliasCodes.split(",")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化别名数组到存储值.
|
||||
*/
|
||||
public static String toAliasCodesJson(Collection<String> aliasCodes) {
|
||||
List<String> values = normalizeCodes(aliasCodes);
|
||||
if (values.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return JacksonUtils.toJson(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造完整匹配国家码集合.
|
||||
*/
|
||||
public static Set<String> buildMatchCodes(String alphaTwo, String alphaThree,
|
||||
Collection<String> aliasCodes) {
|
||||
LinkedHashSet<String> result = new LinkedHashSet<>();
|
||||
appendCode(result, alphaTwo);
|
||||
appendCode(result, alphaThree);
|
||||
if (aliasCodes != null) {
|
||||
aliasCodes.forEach(code -> appendCode(result, code));
|
||||
}
|
||||
|
||||
if (result.stream().anyMatch(CountryCodeAliasUtils::isSaudiCode)) {
|
||||
result.add(SA);
|
||||
result.add(KSA);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化国家码列表.
|
||||
*/
|
||||
public static List<String> normalizeCodes(Collection<String> codes) {
|
||||
if (codes == null || codes.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
LinkedHashSet<String> result = new LinkedHashSet<>();
|
||||
codes.stream().map(CountryCodeAliasUtils::normalize).filter(StringUtils::isNotBlank)
|
||||
.forEach(result::add);
|
||||
return new ArrayList<>(result);
|
||||
}
|
||||
|
||||
private static void appendCode(Set<String> result, String code) {
|
||||
String normalized = normalize(code);
|
||||
if (StringUtils.isNotBlank(normalized)) {
|
||||
result.add(normalized);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,11 @@ package com.red.circle.other.inner.model.cmd.sys;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.red.circle.framework.core.dto.CommonCommand;
|
||||
import java.io.Serial;
|
||||
import java.sql.Timestamp;
|
||||
import lombok.Data;
|
||||
import com.red.circle.framework.core.dto.CommonCommand;
|
||||
import java.io.Serial;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ -51,10 +52,15 @@ public class SysCountryCodeCmd extends CommonCommand {
|
||||
*/
|
||||
private String countryName;
|
||||
|
||||
/**
|
||||
* 别名.
|
||||
*/
|
||||
private String aliasName;
|
||||
/**
|
||||
* 别名.
|
||||
*/
|
||||
private String aliasName;
|
||||
|
||||
/**
|
||||
* 国家码别名集合.
|
||||
*/
|
||||
private List<String> countryCodeAliases;
|
||||
|
||||
/**
|
||||
* 代码分配情况.
|
||||
|
||||
@ -2,10 +2,11 @@ package com.red.circle.other.inner.model.dto.sys;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.red.circle.framework.dto.DTO;
|
||||
import java.io.Serial;
|
||||
import java.sql.Timestamp;
|
||||
import lombok.Data;
|
||||
import com.red.circle.framework.dto.DTO;
|
||||
import java.io.Serial;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ -51,10 +52,15 @@ public class SysCountryCodeDTO extends DTO {
|
||||
*/
|
||||
private String countryName;
|
||||
|
||||
/**
|
||||
* 别名.
|
||||
*/
|
||||
private String aliasName;
|
||||
/**
|
||||
* 别名.
|
||||
*/
|
||||
private String aliasName;
|
||||
|
||||
/**
|
||||
* 国家码别名集合.
|
||||
*/
|
||||
private List<String> countryCodeAliases;
|
||||
|
||||
/**
|
||||
* 代码分配情况.
|
||||
|
||||
@ -64,10 +64,12 @@ framework:
|
||||
red-circle:
|
||||
console:
|
||||
security:
|
||||
ignore-urls:
|
||||
- /console/account/login
|
||||
- /console/actuator/**
|
||||
- /console/datav/active/user-country-code
|
||||
- /console/datav/online/user/count
|
||||
- /console/datav/online/room/count
|
||||
- /console/user/base/info/im/sig
|
||||
ignore-urls:
|
||||
- /console/account/login
|
||||
- /console/actuator/**
|
||||
- /console/internal/resident-activity/invite/grant-gold
|
||||
- /console/internal/resident-activity/invite/grant-props
|
||||
- /console/datav/active/user-country-code
|
||||
- /console/datav/online/user/count
|
||||
- /console/datav/online/room/count
|
||||
- /console/user/base/info/im/sig
|
||||
|
||||
@ -2,14 +2,16 @@ package com.red.circle.order.adapter.app;
|
||||
|
||||
import com.red.circle.common.business.dto.cmd.IdLongCmd;
|
||||
import com.red.circle.common.business.dto.cmd.IdStringCmd;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.ApplicationCommodityCardV2CO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayApplicationCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayCountryCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.UserProfileAndCountryCO;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderReceiptCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayWebApplicationCommodityCmd;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.ApplicationCommodityCardV2CO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayApplicationCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayCountryCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayOrderStatusCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.UserProfileAndCountryCO;
|
||||
import com.red.circle.order.app.dto.cmd.PayOrderStatusCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderReceiptCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayWebApplicationCommodityCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayWebUserCmd;
|
||||
import com.red.circle.order.app.service.InAppPurchaseProductService;
|
||||
import com.red.circle.order.app.service.WebPayService;
|
||||
@ -99,13 +101,26 @@ public class WebPayRestController {
|
||||
* @eo.method post
|
||||
* @eo.request-type json
|
||||
*/
|
||||
@PostMapping("/recharge")
|
||||
public PlaceAnOrderResponseCO placeAnOrder(@RequestBody @Validated PayPlaceAnOrderCmd cmd) {
|
||||
return inAppPurchaseProductService.placeAnOrder(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付收据 (后续版本计划移除).
|
||||
@PostMapping("/recharge")
|
||||
public PlaceAnOrderResponseCO placeAnOrder(@RequestBody @Validated PayPlaceAnOrderCmd cmd) {
|
||||
return inAppPurchaseProductService.placeAnOrder(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付单状态.
|
||||
*
|
||||
* @eo.name 查询支付单状态.
|
||||
* @eo.url /order-status
|
||||
* @eo.method get
|
||||
* @eo.request-type formdata
|
||||
*/
|
||||
@GetMapping("/order-status")
|
||||
public PayOrderStatusCO orderStatus(@Validated PayOrderStatusCmd cmd) {
|
||||
return inAppPurchaseProductService.orderStatus(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付收据 (后续版本计划移除).
|
||||
*
|
||||
* @eo.name 支付收据 (后续版本计划移除).
|
||||
* @eo.url /pay-receipt
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
package com.red.circle.order.app.command.pay.web;
|
||||
|
||||
import com.red.circle.component.pay.paymax.PayMaxUtils;
|
||||
import com.red.circle.order.app.common.InAppPurchaseCommon;
|
||||
import com.red.circle.order.domain.order.MiFaPayReceivePaymentNotice;
|
||||
import com.red.circle.order.infra.config.MiFaPayProperties;
|
||||
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseCollectionReceiptService;
|
||||
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseDetailsService;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseEventNotice;
|
||||
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import com.red.circle.component.pay.paymax.PayMaxUtils;
|
||||
import com.red.circle.order.app.common.InAppPurchaseCommon;
|
||||
import com.red.circle.order.app.common.MiFaPayMysqlOrderSupport;
|
||||
import com.red.circle.order.domain.order.MiFaPayReceivePaymentNotice;
|
||||
import com.red.circle.order.infra.config.MiFaPayProperties;
|
||||
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseCollectionReceiptService;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
|
||||
import com.red.circle.order.infra.database.rds.service.order.OrderUserPurchasePayNoticeService;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePay;
|
||||
import com.red.circle.order.infra.database.rds.service.order.OrderUserPurchasePayService;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
@ -30,11 +30,12 @@ public class MiFaPayServerNoticeReceivePaymentCmdExe {
|
||||
|
||||
private static final String SUCCESS = "SUCCESS";
|
||||
private static final String FAIL = "FAIL";
|
||||
|
||||
private final MiFaPayProperties miFaPayProperties;
|
||||
private final InAppPurchaseCommon inAppPurchaseCommon;
|
||||
private final InAppPurchaseDetailsService inAppPurchaseDetailsService;
|
||||
private final InAppPurchaseCollectionReceiptService inAppPurchaseCollectionReceiptService;
|
||||
|
||||
private final MiFaPayProperties miFaPayProperties;
|
||||
private final InAppPurchaseCommon inAppPurchaseCommon;
|
||||
private final InAppPurchaseCollectionReceiptService inAppPurchaseCollectionReceiptService;
|
||||
private final OrderUserPurchasePayNoticeService orderUserPurchasePayNoticeService;
|
||||
private final OrderUserPurchasePayService orderUserPurchasePayService;
|
||||
|
||||
/**
|
||||
* 处理MiFaPay支付回调
|
||||
@ -76,70 +77,74 @@ public class MiFaPayServerNoticeReceivePaymentCmdExe {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
MiFaPayReceivePaymentNotice.MiFaPayNoticeData noticeData = notice.getNoticeData();
|
||||
|
||||
// 查询订单
|
||||
InAppPurchaseDetails order = inAppPurchaseDetailsService.getById(noticeData.getOrderId());
|
||||
if (Objects.isNull(order)) {
|
||||
log.error("MiFaPay回调未找到订单: orderId={}", noticeData.getOrderId());
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// 检查订单状态,避免重复处理
|
||||
if (!Objects.equals(order.getStatus(), InAppPurchaseStatus.CREATE)) {
|
||||
log.warn("MiFaPay订单已处理: orderId={}, status={}", order.getId(), order.getStatus());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// 记录回调通知
|
||||
inAppPurchaseDetailsService.addPayNotices(order.getId(),
|
||||
new InAppPurchaseEventNotice()
|
||||
.setEventId(notice.getSign())
|
||||
.setNoticeType("mifapay-" + noticeData.getOrderStatus())
|
||||
.setNoticeData(notice)
|
||||
.setCreateTime(TimestampUtils.now())
|
||||
);
|
||||
|
||||
// 处理支付成功
|
||||
if (noticeData.isSuccess()) {
|
||||
if (!Objects.equals(order.statusEqCreate(), Boolean.TRUE)) {
|
||||
log.warn("MiFaPay订单状态不是CREATE: orderId={}", order.getId());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// 收款单
|
||||
if (order.receiptTypeEqReceipt()) {
|
||||
inAppPurchaseCommon.inAppPurchaseReceipt(order);
|
||||
log.info("MiFaPay收款单处理成功: orderId={}", order.getId());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// 付款单
|
||||
if (order.receiptTypeEqPayment()) {
|
||||
inAppPurchaseCommon.inAppPurchasePayment(order);
|
||||
log.info("MiFaPay付款单处理成功: orderId={}", order.getId());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
log.error("MiFaPay订单类型错误: orderId={}", order.getId());
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// 处理支付失败
|
||||
if (noticeData.isFailed()) {
|
||||
if (order.receiptTypeEqReceipt()) {
|
||||
inAppPurchaseCollectionReceiptService.updateStatusSuccessFail(order.getId());
|
||||
}
|
||||
inAppPurchaseDetailsService.updateStatusReason(
|
||||
order.getId(),
|
||||
InAppPurchaseStatus.FAIL,
|
||||
String.format("MiFaPay支付失败: %s", noticeData.getOrderStatus())
|
||||
);
|
||||
log.info("MiFaPay支付失败处理完成: orderId={}", order.getId());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
log.error("MiFaPay未知订单状态: orderId={}, status={}", order.getId(), noticeData.getOrderStatus());
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
MiFaPayReceivePaymentNotice.MiFaPayNoticeData noticeData = notice.getNoticeData();
|
||||
|
||||
OrderUserPurchasePay mysqlOrder = getMysqlOrder(noticeData.getOrderId());
|
||||
if (Objects.isNull(mysqlOrder)) {
|
||||
log.error("MiFaPay回调未找到MySQL订单: orderId={}", noticeData.getOrderId());
|
||||
return FAIL;
|
||||
}
|
||||
return handleMysqlOrder(notice, noticeData, mysqlOrder);
|
||||
}
|
||||
|
||||
private String handleMysqlOrder(MiFaPayReceivePaymentNotice notice,
|
||||
MiFaPayReceivePaymentNotice.MiFaPayNoticeData noticeData,
|
||||
OrderUserPurchasePay mysqlOrder) {
|
||||
orderUserPurchasePayNoticeService.addNotice(
|
||||
mysqlOrder.getId(),
|
||||
notice.getSign(),
|
||||
"mifapay-" + noticeData.getOrderStatus(),
|
||||
notice,
|
||||
mysqlOrder.getUpdateUser()
|
||||
);
|
||||
|
||||
if (!Objects.equals(mysqlOrder.getPayStatus(), MiFaPayMysqlOrderSupport.PAY_STATUS_PREPAYMENT)) {
|
||||
log.warn("MiFaPay订单已处理(MySQL): orderId={}, status={}",
|
||||
mysqlOrder.getId(), mysqlOrder.getPayStatus());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
InAppPurchaseDetails order = MiFaPayMysqlOrderSupport.toInAppPurchaseDetails(mysqlOrder);
|
||||
|
||||
if (noticeData.isSuccess()) {
|
||||
if (order.receiptTypeEqReceipt()) {
|
||||
inAppPurchaseCommon.inAppPurchaseReceipt(order,
|
||||
() -> orderUserPurchasePayService.updateSuccess(mysqlOrder.getId()));
|
||||
log.info("MiFaPay收款单处理成功(MySQL): orderId={}", mysqlOrder.getId());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (order.receiptTypeEqPayment()) {
|
||||
inAppPurchaseCommon.inAppPurchasePayment(order,
|
||||
() -> orderUserPurchasePayService.updateSuccess(mysqlOrder.getId()));
|
||||
log.info("MiFaPay付款单处理成功(MySQL): orderId={}", mysqlOrder.getId());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
log.error("MiFaPay订单类型错误(MySQL): orderId={}", mysqlOrder.getId());
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
if (noticeData.isFailed()) {
|
||||
if (order.receiptTypeEqReceipt() && StringUtils.isNotBlank(mysqlOrder.getReferenceId())) {
|
||||
inAppPurchaseCollectionReceiptService.updateStatusSuccessFail(
|
||||
mysqlOrder.getReferenceId());
|
||||
}
|
||||
orderUserPurchasePayService.updateFail(
|
||||
mysqlOrder.getId(),
|
||||
String.format("MiFaPay支付失败: %s", noticeData.getOrderStatus())
|
||||
);
|
||||
log.info("MiFaPay支付失败处理完成(MySQL): orderId={}", mysqlOrder.getId());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
log.error("MiFaPay未知订单状态(MySQL): orderId={}, status={}",
|
||||
mysqlOrder.getId(), noticeData.getOrderStatus());
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
private OrderUserPurchasePay getMysqlOrder(String orderId) {
|
||||
Long mysqlOrderId = MiFaPayMysqlOrderSupport.parseOrderId(orderId);
|
||||
return mysqlOrderId == null ? null : orderUserPurchasePayService.getById(mysqlOrderId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
package com.red.circle.order.app.command.pay.web;
|
||||
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.order.app.common.MiFaPayMysqlOrderSupport;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayOrderStatusCO;
|
||||
import com.red.circle.order.app.dto.cmd.PayOrderStatusCmd;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePay;
|
||||
import com.red.circle.order.infra.database.rds.service.order.OrderUserPurchasePayService;
|
||||
import com.red.circle.order.inner.asserts.OrderErrorCode;
|
||||
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 支付单状态查询.
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class PayWebOrderStatusQueryExe {
|
||||
|
||||
private final OrderUserPurchasePayService orderUserPurchasePayService;
|
||||
|
||||
public PayOrderStatusCO execute(PayOrderStatusCmd cmd) {
|
||||
OrderUserPurchasePay mysqlOrder = getMysqlOrder(cmd.getOrderId());
|
||||
ResponseAssert.notNull(OrderErrorCode.NO_PURCHASE_RECORD_FOUND, mysqlOrder);
|
||||
ResponseAssert.isTrue(OrderErrorCode.NO_PURCHASE_RECORD_FOUND,
|
||||
Objects.equals(mysqlOrder.getUserId(), cmd.getReqUserId()));
|
||||
InAppPurchaseStatus status = MiFaPayMysqlOrderSupport
|
||||
.toInAppPurchaseStatus(mysqlOrder.getPayStatus());
|
||||
return new PayOrderStatusCO()
|
||||
.setOrderId(Objects.toString(mysqlOrder.getId(), null))
|
||||
.setTradeNo(mysqlOrder.getFactoryOrderId())
|
||||
.setStatus(Objects.toString(status, null))
|
||||
.setSuccess(MiFaPayMysqlOrderSupport.isSuccess(mysqlOrder.getPayStatus()))
|
||||
.setFinished(MiFaPayMysqlOrderSupport.isFinished(mysqlOrder.getPayStatus()))
|
||||
.setReason(mysqlOrder.getReason())
|
||||
.setFactoryCode(mysqlOrder.getFactoryCode())
|
||||
.setFactoryChannelCode(mysqlOrder.getPaymentChannel())
|
||||
.setCurrency(mysqlOrder.getPaymentUnit())
|
||||
.setAmount(mysqlOrder.getPaymentAmount())
|
||||
.setUpdateTime(mysqlOrder.getUpdateTime());
|
||||
}
|
||||
|
||||
private OrderUserPurchasePay getMysqlOrder(String orderId) {
|
||||
Long mysqlOrderId = MiFaPayMysqlOrderSupport.parseOrderId(orderId);
|
||||
return mysqlOrderId == null ? null : orderUserPurchasePayService.getById(mysqlOrderId);
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,8 @@
|
||||
package com.red.circle.order.app.command.pay.web.strategy;
|
||||
|
||||
import com.red.circle.component.pay.paymax.service.PlaceAnOrderParam;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
package com.red.circle.order.app.command.pay.web.strategy;
|
||||
|
||||
import com.red.circle.component.pay.paymax.service.PlaceAnOrderParam;
|
||||
import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.response.ResponseErrorCode;
|
||||
import com.red.circle.order.app.common.MiFaPayPlaceAnOrderParam;
|
||||
import com.red.circle.order.app.dto.clientobject.MiFaPayResponseCO;
|
||||
@ -101,13 +102,13 @@ public class MiFaPayWebPayPlaceAnOrderStrategy implements PayWebPlaceAnOrderStra
|
||||
.amount(amountInCents)
|
||||
.currency(details.getCurrency())
|
||||
.payWay(extractPayWay(details.getChannelCode()))
|
||||
.payType(details.getFactoryChannel())
|
||||
.userIp(details.getRequestIp())
|
||||
.returnUrl(details.getSuccessRedirectUrl())
|
||||
.notifyUrl(MiFaPayService.NOTIFY_URL)
|
||||
.language("en")
|
||||
.email(memberInfo.getEmail())
|
||||
.countryCode(replaceCountryCode(details.getCountryCode()))
|
||||
.payType(details.getFactoryChannel())
|
||||
.userIp(details.getRequestIp())
|
||||
.returnUrl(details.getSuccessRedirectUrl())
|
||||
.notifyUrl(miFaPayService.getNotifyUrl())
|
||||
.language("en")
|
||||
.email(memberInfo.getEmail())
|
||||
.countryCode(replaceCountryCode(details.getCountryCode()))
|
||||
.firstName(memberInfo.getFirstName())
|
||||
.lastName(memberInfo.getLastName())
|
||||
.phone(memberInfo.getPhone())
|
||||
@ -125,13 +126,9 @@ public class MiFaPayWebPayPlaceAnOrderStrategy implements PayWebPlaceAnOrderStra
|
||||
return underscoreIndex > 0 ? channelCode.substring(0, underscoreIndex) : channelCode;
|
||||
}
|
||||
|
||||
private static String replaceCountryCode(String countryCode) {
|
||||
if ("KSA".equalsIgnoreCase(countryCode)) {
|
||||
return countryCode.replaceAll("K", "");
|
||||
}
|
||||
|
||||
return countryCode;
|
||||
}
|
||||
private static String replaceCountryCode(String countryCode) {
|
||||
return CountryCodeAliasUtils.normalizeSaudiCode(countryCode);
|
||||
}
|
||||
|
||||
|
||||
private String getPlaceAnOrderPaymentDetailParam(PayPlaceAnOrderDetailsV2 details) {
|
||||
|
||||
@ -4,16 +4,19 @@ import com.google.api.client.util.Maps;
|
||||
import com.red.circle.component.pay.paymax.PayMaxUtils;
|
||||
import com.red.circle.framework.core.request.RequestClientEnum;
|
||||
import com.red.circle.framework.web.props.EnvProperties;
|
||||
import com.red.circle.order.app.common.PayerMaxProperties;
|
||||
import com.red.circle.order.app.common.QuoteQueryParam;
|
||||
import com.red.circle.order.app.common.QuoteQueryResponse;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseDetailsService;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseEventNotice;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseFactory;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseStatusStep;
|
||||
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
|
||||
import com.red.circle.order.app.common.MiFaPayMysqlOrderSupport;
|
||||
import com.red.circle.order.app.common.PayerMaxProperties;
|
||||
import com.red.circle.order.app.common.QuoteQueryParam;
|
||||
import com.red.circle.order.app.common.QuoteQueryResponse;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseDetailsService;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseEventNotice;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseFactory;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseStatusStep;
|
||||
import com.red.circle.order.infra.database.rds.service.order.OrderUserPurchasePayNoticeService;
|
||||
import com.red.circle.order.infra.database.rds.service.order.OrderUserPurchasePayService;
|
||||
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.http.RcHttpClient;
|
||||
import com.red.circle.tool.core.json.JacksonUtils;
|
||||
@ -32,21 +35,36 @@ import org.springframework.stereotype.Service;
|
||||
@RequiredArgsConstructor
|
||||
public class PayPlaceAnOrderService {
|
||||
|
||||
private final EnvProperties envProperties;
|
||||
private final InAppPurchaseDetailsService inAppPurchaseDetailsService;
|
||||
private final FactoryPlaceAnOrderStrategyV2 factoryPlaceAnOrderStrategyV2;
|
||||
private final PayerMaxProperties payerMaxProperties;
|
||||
private final RcHttpClient rcHttpClient = RcHttpClient.builder().build();
|
||||
private final EnvProperties envProperties;
|
||||
private final InAppPurchaseDetailsService inAppPurchaseDetailsService;
|
||||
private final OrderUserPurchasePayNoticeService orderUserPurchasePayNoticeService;
|
||||
private final OrderUserPurchasePayService orderUserPurchasePayService;
|
||||
private final FactoryPlaceAnOrderStrategyV2 factoryPlaceAnOrderStrategyV2;
|
||||
private final PayerMaxProperties payerMaxProperties;
|
||||
private final RcHttpClient rcHttpClient = RcHttpClient.builder().build();
|
||||
|
||||
public PlaceAnOrderResponseCO doRequest(PayPlaceAnOrderDetailsV2 param) {
|
||||
// 第三方:请求下单
|
||||
PlaceAnOrderResponseCO response = factoryPlaceAnOrderStrategyV2.getStrategy(
|
||||
param.getStrategyCode())
|
||||
.doOperation(param);
|
||||
|
||||
// 创建站内:预支付订单.
|
||||
inAppPurchaseDetailsService.create(
|
||||
new InAppPurchaseDetails()
|
||||
PlaceAnOrderResponseCO response = factoryPlaceAnOrderStrategyV2.getStrategy(
|
||||
param.getStrategyCode())
|
||||
.doOperation(param);
|
||||
|
||||
if (MiFaPayMysqlOrderSupport.isMiFaPay(param.getFactoryCode())) {
|
||||
Long purchasePayId = MiFaPayMysqlOrderSupport.parseOrderId(param.getOrderId());
|
||||
orderUserPurchasePayService.save(
|
||||
MiFaPayMysqlOrderSupport.buildPrepaymentOrder(param, response, env()));
|
||||
orderUserPurchasePayNoticeService.addNotice(
|
||||
purchasePayId,
|
||||
"custom-request-response-param",
|
||||
"API-INTERNAL-PARAMETERS",
|
||||
response.extra(),
|
||||
param.getCreateUserId());
|
||||
return response;
|
||||
}
|
||||
|
||||
// 创建站内:预支付订单.
|
||||
inAppPurchaseDetailsService.create(
|
||||
new InAppPurchaseDetails()
|
||||
.setId(param.getOrderId())
|
||||
.setTrackId(param.getApplicationId())
|
||||
.setTrackCommodityType(param.getAppCommodityType())
|
||||
|
||||
@ -77,24 +77,31 @@ public class InAppPurchaseCommon {
|
||||
private final InAppPurchaseCollectionReceiptService inAppPurchaseCollectionReceiptService;
|
||||
private final UserLevelClient userLevelClient;
|
||||
private final PropsActivityClient propsActivityClient;
|
||||
private final UserOneTimeTaskClient userOneTimeTaskClient;
|
||||
private final UserProfileClient userProfileClient;
|
||||
|
||||
public void inAppPurchaseReceipt(InAppPurchaseDetails order) {
|
||||
|
||||
if (!order.receiptTypeEqReceipt()) {
|
||||
return;
|
||||
}
|
||||
private final UserOneTimeTaskClient userOneTimeTaskClient;
|
||||
private final UserProfileClient userProfileClient;
|
||||
|
||||
public void inAppPurchaseReceipt(InAppPurchaseDetails order) {
|
||||
inAppPurchaseReceipt(order,
|
||||
() -> inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS));
|
||||
}
|
||||
|
||||
public void inAppPurchaseReceipt(InAppPurchaseDetails order, Runnable successHandler) {
|
||||
Runnable finalSuccessHandler = successHandler != null ? successHandler : () -> {
|
||||
};
|
||||
|
||||
if (!order.receiptTypeEqReceipt()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Objects.equals(order.getStatus(), InAppPurchaseStatus.CREATE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(order.getProducts())) {
|
||||
inAppPurchaseCollectionReceiptService.updateStatusSuccess(order.getTrackId());
|
||||
inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(order.getProducts())) {
|
||||
inAppPurchaseCollectionReceiptService.updateStatusSuccess(order.getTrackId());
|
||||
finalSuccessHandler.run();
|
||||
return;
|
||||
}
|
||||
|
||||
saveOrderPurchaseHistory(order);
|
||||
|
||||
@ -121,14 +128,21 @@ public class InAppPurchaseCommon {
|
||||
}).filter(Objects::nonNull).collect(Collectors.toList())
|
||||
)
|
||||
);
|
||||
|
||||
inAppPurchaseCollectionReceiptService.updateStatusSuccess(order.getTrackId());
|
||||
inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS);
|
||||
}
|
||||
|
||||
public void inAppPurchasePayment(InAppPurchaseDetails order) {
|
||||
InAppPurchaseProduct product = order.firstProduct();
|
||||
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_MAPPING_INFO, product);
|
||||
|
||||
inAppPurchaseCollectionReceiptService.updateStatusSuccess(order.getTrackId());
|
||||
finalSuccessHandler.run();
|
||||
}
|
||||
|
||||
public void inAppPurchasePayment(InAppPurchaseDetails order) {
|
||||
inAppPurchasePayment(order,
|
||||
() -> inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS));
|
||||
}
|
||||
|
||||
public void inAppPurchasePayment(InAppPurchaseDetails order, Runnable successHandler) {
|
||||
Runnable finalSuccessHandler = successHandler != null ? successHandler : () -> {
|
||||
};
|
||||
InAppPurchaseProduct product = order.firstProduct();
|
||||
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_MAPPING_INFO, product);
|
||||
|
||||
saveOrderPurchaseHistory(order);
|
||||
|
||||
@ -136,13 +150,13 @@ public class InAppPurchaseCommon {
|
||||
inAppPurchase(order);
|
||||
}
|
||||
|
||||
if (PayApplicationCommodityType.FREIGHT_GOLD.eq(product.getCode())) {
|
||||
inShipPurchase(order);
|
||||
}
|
||||
|
||||
// 修改订单状态
|
||||
inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS);
|
||||
}
|
||||
if (PayApplicationCommodityType.FREIGHT_GOLD.eq(product.getCode())) {
|
||||
inShipPurchase(order);
|
||||
}
|
||||
|
||||
// 修改订单状态
|
||||
finalSuccessHandler.run();
|
||||
}
|
||||
|
||||
|
||||
private void inAppPurchase(InAppPurchaseDetails order) {
|
||||
|
||||
@ -0,0 +1,168 @@
|
||||
package com.red.circle.order.app.common;
|
||||
|
||||
import com.red.circle.framework.core.request.RequestClientEnum;
|
||||
import com.red.circle.order.app.command.pay.web.strategy.PayPlaceAnOrderDetailsV2;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseFactory;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseProduct;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePay;
|
||||
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseReceiptType;
|
||||
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* MiFaPay MySQL订单映射工具.
|
||||
*/
|
||||
public final class MiFaPayMysqlOrderSupport {
|
||||
|
||||
public static final String FACTORY_CODE = "MIFA_PAY";
|
||||
public static final String PAY_STATUS_PREPAYMENT = "PREPAYMENT";
|
||||
public static final String PAY_STATUS_SUCCESSFUL = "SUCCESSFUL";
|
||||
public static final String PAY_STATUS_FAIL = "FAIL";
|
||||
public static final String REFUND_STATUS_NONE = "NONE";
|
||||
|
||||
private MiFaPayMysqlOrderSupport() {
|
||||
}
|
||||
|
||||
public static boolean isMiFaPay(String factoryCode) {
|
||||
return Objects.equals(FACTORY_CODE, factoryCode);
|
||||
}
|
||||
|
||||
public static Long parseOrderId(String orderId) {
|
||||
if (StringUtils.isBlank(orderId)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Long.valueOf(orderId.trim());
|
||||
} catch (NumberFormatException ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static OrderUserPurchasePay buildPrepaymentOrder(PayPlaceAnOrderDetailsV2 param,
|
||||
PlaceAnOrderResponseCO response, String env) {
|
||||
Timestamp now = TimestampUtils.now();
|
||||
InAppPurchaseProduct product = firstProduct(param.getProducts());
|
||||
Long referenceId = parseOrderId(param.getApplicationId());
|
||||
|
||||
return new OrderUserPurchasePay()
|
||||
.setId(parseOrderId(param.getOrderId()))
|
||||
.setEvn(env)
|
||||
.setSysOrigin(param.getSysOrigin())
|
||||
.setUserId(param.getAcceptUserId())
|
||||
.setFactoryCode(param.getFactoryCode())
|
||||
.setFactoryOrderId(Objects.toString(response.getTradeNo(), ""))
|
||||
.setReferenceId(Objects.toString(param.getApplicationId(), ""))
|
||||
.setReceiptType(Objects.toString(param.getReceiptType(),
|
||||
InAppPurchaseReceiptType.PAYMENT.name()))
|
||||
.setPaymentChannel(Objects.toString(param.getChannelCode(), ""))
|
||||
.setFactoryChannel(Objects.toString(param.getFactoryChannel(), ""))
|
||||
.setProductCode(product != null ? Objects.toString(product.getCode(), "") : "")
|
||||
.setProductContent(product != null ? Objects.toString(product.getContent(), "") : "")
|
||||
.setProductDescriptor(Objects.toString(param.getProductDescriptor(), ""))
|
||||
.setPaymentUnit(Objects.toString(param.getCurrency(), ""))
|
||||
.setPaymentAmount(defaultDecimal(param.getAmount()))
|
||||
.setComputeUsdAmount(defaultDecimal(param.getAmountUsd()))
|
||||
.setComputeUsdRate(computeUsdRate(param.getAmount(), param.getAmountUsd()))
|
||||
.setGiveAwayContent("")
|
||||
.setCountryId(param.getCountry() != null ? param.getCountry().getId() : 0L)
|
||||
.setCountryCode(Objects.toString(response.getCountryCode(), param.getCountryCode()))
|
||||
.setPayCountryId(param.getPayCountry() != null ? param.getPayCountry().getId() : 0L)
|
||||
.setPayStatus(PAY_STATUS_PREPAYMENT)
|
||||
.setReason("")
|
||||
.setRefundStatus(REFUND_STATUS_NONE)
|
||||
.setReceiptDetailsId(referenceId != null ? referenceId : 0L)
|
||||
.setCreateTime(now)
|
||||
.setUpdateTime(now)
|
||||
.setCreateUser(param.getCreateUserId())
|
||||
.setUpdateUser(param.getCreateUserId());
|
||||
}
|
||||
|
||||
public static InAppPurchaseDetails toInAppPurchaseDetails(OrderUserPurchasePay order) {
|
||||
List<InAppPurchaseProduct> products = StringUtils.isBlank(order.getProductCode())
|
||||
? Collections.emptyList()
|
||||
: List.of(new InAppPurchaseProduct()
|
||||
.setId(order.getReceiptDetailsId())
|
||||
.setName(order.getProductCode())
|
||||
.setCode(order.getProductCode())
|
||||
.setDescribe(order.getProductDescriptor())
|
||||
.setContent(order.getProductContent())
|
||||
.setAmountUsd(defaultDecimal(order.getComputeUsdAmount()))
|
||||
.setQuantity(1));
|
||||
|
||||
return new InAppPurchaseDetails()
|
||||
.setId(Objects.toString(order.getId(), null))
|
||||
.setReceiptType(parseReceiptType(order.getReceiptType()))
|
||||
.setTrackId(order.getReferenceId())
|
||||
.setSysOrigin(order.getSysOrigin())
|
||||
.setAcceptUserId(order.getUserId())
|
||||
.setOrderId(order.getFactoryOrderId())
|
||||
.setEnv(order.getEvn())
|
||||
.setFactory(new InAppPurchaseFactory()
|
||||
.setPlatform(RequestClientEnum.H5.getClientName())
|
||||
.setFactoryCode(order.getFactoryCode())
|
||||
.setFactoryChannelCode(order.getPaymentChannel()))
|
||||
.setProducts(products)
|
||||
.setProductDescriptor(order.getProductDescriptor())
|
||||
.setCountryCode(order.getCountryCode())
|
||||
.setCurrency(order.getPaymentUnit())
|
||||
.setAmount(defaultDecimal(order.getPaymentAmount()))
|
||||
.setAmountUsd(defaultDecimal(order.getComputeUsdAmount()))
|
||||
.setTrialPeriod(Boolean.FALSE)
|
||||
.setStatus(toInAppPurchaseStatus(order.getPayStatus()))
|
||||
.setReason(order.getReason())
|
||||
.setCreateTime(order.getCreateTime())
|
||||
.setUpdateTime(order.getUpdateTime())
|
||||
.setCreateUser(order.getCreateUser());
|
||||
}
|
||||
|
||||
public static InAppPurchaseStatus toInAppPurchaseStatus(String payStatus) {
|
||||
if (Objects.equals(PAY_STATUS_SUCCESSFUL, payStatus)) {
|
||||
return InAppPurchaseStatus.SUCCESS;
|
||||
}
|
||||
if (Objects.equals(PAY_STATUS_FAIL, payStatus)) {
|
||||
return InAppPurchaseStatus.FAIL;
|
||||
}
|
||||
return InAppPurchaseStatus.CREATE;
|
||||
}
|
||||
|
||||
public static boolean isSuccess(String payStatus) {
|
||||
return Objects.equals(PAY_STATUS_SUCCESSFUL, payStatus);
|
||||
}
|
||||
|
||||
public static boolean isFinished(String payStatus) {
|
||||
return isSuccess(payStatus) || Objects.equals(PAY_STATUS_FAIL, payStatus);
|
||||
}
|
||||
|
||||
private static String computeUsdRate(BigDecimal paymentAmount, BigDecimal usdAmount) {
|
||||
if (paymentAmount == null || usdAmount == null || BigDecimal.ZERO.compareTo(usdAmount) == 0) {
|
||||
return "";
|
||||
}
|
||||
return paymentAmount.divide(usdAmount, 8, RoundingMode.HALF_UP)
|
||||
.stripTrailingZeros()
|
||||
.toPlainString();
|
||||
}
|
||||
|
||||
private static InAppPurchaseProduct firstProduct(List<InAppPurchaseProduct> products) {
|
||||
return products == null || products.isEmpty() ? null : products.get(0);
|
||||
}
|
||||
|
||||
private static InAppPurchaseReceiptType parseReceiptType(String receiptType) {
|
||||
if (Objects.equals(InAppPurchaseReceiptType.RECEIPT.name(), receiptType)) {
|
||||
return InAppPurchaseReceiptType.RECEIPT;
|
||||
}
|
||||
return InAppPurchaseReceiptType.PAYMENT;
|
||||
}
|
||||
|
||||
private static BigDecimal defaultDecimal(BigDecimal value) {
|
||||
return value != null ? value : BigDecimal.ZERO;
|
||||
}
|
||||
}
|
||||
@ -20,23 +20,26 @@ import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
|
||||
import com.red.circle.order.app.command.pay.app.execute.AppInAppPurchaseCmdExe;
|
||||
import com.red.circle.order.app.command.pay.app.execute.AppleAutoSubscriptionNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.app.execute.GoogleCheckOneTimeProductNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.AirwallexServerNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.ClipspayServerNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.CollectionReceiptQueryExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayPalServerNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayWebPlaceAnOrderCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayerMaxServerNoticeReceivePaymentCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayerMaxServerNoticeRefundNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.AirwallexServerNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.ClipspayServerNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.CollectionReceiptQueryExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayPalServerNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayWebOrderStatusQueryExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayWebPlaceAnOrderCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayerMaxServerNoticeReceivePaymentCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.PayerMaxServerNoticeRefundNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.PaynicornServerNoticeCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.MiFaPayServerNoticeReceivePaymentCmdExe;
|
||||
import com.red.circle.order.app.command.pay.web.ReceiptPayWebPlaceAnOrderReceiptCmdExe;
|
||||
import com.red.circle.order.app.dto.clientobject.PayMaxResponseCO;
|
||||
import com.red.circle.order.app.dto.clientobject.PayerMaxResponseV2CO;
|
||||
import com.red.circle.order.app.dto.clientobject.PurchaseReceiptCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.app.dto.cmd.AbstractPurchaseCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderReceiptCmd;
|
||||
import com.red.circle.order.app.dto.clientobject.PayMaxResponseCO;
|
||||
import com.red.circle.order.app.dto.clientobject.PayerMaxResponseV2CO;
|
||||
import com.red.circle.order.app.dto.clientobject.PurchaseReceiptCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayOrderStatusCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.app.dto.cmd.AbstractPurchaseCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayOrderStatusCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderReceiptCmd;
|
||||
import com.red.circle.tool.core.date.LocalDateTimeUtils;
|
||||
import com.red.circle.tool.core.json.JacksonUtils;
|
||||
|
||||
@ -58,10 +61,11 @@ import org.springframework.stereotype.Service;
|
||||
@RequiredArgsConstructor
|
||||
public class InAppPurchaseProductServiceImpl implements InAppPurchaseProductService {
|
||||
|
||||
private final AppInAppPurchaseCmdExe appInAppPurchaseCmdExe;
|
||||
private final PayWebPlaceAnOrderCmdExe payWebPlaceAnOrderCmdExe;
|
||||
private final PayPalServerNoticeCmdExe payPalServerNoticeCmdExe;
|
||||
private final CollectionReceiptQueryExe collectionReceiptQueryExe;
|
||||
private final AppInAppPurchaseCmdExe appInAppPurchaseCmdExe;
|
||||
private final PayWebPlaceAnOrderCmdExe payWebPlaceAnOrderCmdExe;
|
||||
private final PayWebOrderStatusQueryExe payWebOrderStatusQueryExe;
|
||||
private final PayPalServerNoticeCmdExe payPalServerNoticeCmdExe;
|
||||
private final CollectionReceiptQueryExe collectionReceiptQueryExe;
|
||||
private final ClipspayServerNoticeCmdExe clipspayServerNoticeCmdExe;
|
||||
private final AirwallexServerNoticeCmdExe airwallexServerNoticeCmdExe;
|
||||
private final PaynicornServerNoticeCmdExe paynicornServerNoticeCmdExe;
|
||||
@ -145,12 +149,17 @@ public class InAppPurchaseProductServiceImpl implements InAppPurchaseProductServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceAnOrderResponseCO placeAnOrder(PayPlaceAnOrderCmd cmd) {
|
||||
return payWebPlaceAnOrderCmdExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceAnOrderResponseCO payReceipt(PayPlaceAnOrderReceiptCmd cmd) {
|
||||
public PlaceAnOrderResponseCO placeAnOrder(PayPlaceAnOrderCmd cmd) {
|
||||
return payWebPlaceAnOrderCmdExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOrderStatusCO orderStatus(PayOrderStatusCmd cmd) {
|
||||
return payWebOrderStatusQueryExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlaceAnOrderResponseCO payReceipt(PayPlaceAnOrderReceiptCmd cmd) {
|
||||
return receiptPayWebPlaceAnOrderReceiptCmdExe.execute(cmd);
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
package com.red.circle.order.app.service;
|
||||
|
||||
import com.red.circle.component.pay.paymax.PayMaxUtils;
|
||||
import com.red.circle.order.app.common.MiFaPayPlaceAnOrderParam;
|
||||
import com.red.circle.order.app.dto.clientobject.MiFaPayResponseCO;
|
||||
import com.red.circle.order.infra.config.MiFaPayProperties;
|
||||
import com.red.circle.tool.core.http.RcHttpClient;
|
||||
import com.red.circle.tool.core.json.JacksonUtils;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.red.circle.component.pay.paymax.PayMaxUtils;
|
||||
import com.red.circle.order.app.common.MiFaPayPlaceAnOrderParam;
|
||||
import com.red.circle.order.app.dto.clientobject.MiFaPayResponseCO;
|
||||
import com.red.circle.order.infra.config.MiFaPayProperties;
|
||||
import com.red.circle.tool.core.http.RcHttpClient;
|
||||
import com.red.circle.tool.core.json.JacksonUtils;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@ -20,13 +21,12 @@ import java.util.Objects;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MiFaPayService {
|
||||
|
||||
/**
|
||||
* 下单接口路径
|
||||
*/
|
||||
public static final String NOTIFY_URL = "";
|
||||
private static final String PLACE_ORDER_PATH = "/paygateway/mbpay/order/en_v2";
|
||||
public class MiFaPayService {
|
||||
|
||||
/**
|
||||
* 下单接口路径
|
||||
*/
|
||||
private static final String PLACE_ORDER_PATH = "/paygateway/mbpay/order/en_v2";
|
||||
|
||||
private final String active;
|
||||
private final MiFaPayProperties miFaPayProperties;
|
||||
@ -44,9 +44,11 @@ public class MiFaPayService {
|
||||
* @param param 下单参数
|
||||
* @return 支付响应
|
||||
*/
|
||||
public MiFaPayResponseCO placeAnOrder(MiFaPayPlaceAnOrderParam param) {
|
||||
// 设置商户编号
|
||||
param.setMerNo(miFaPayProperties.getMerNo());
|
||||
public MiFaPayResponseCO placeAnOrder(MiFaPayPlaceAnOrderParam param) {
|
||||
validateRequiredConfig();
|
||||
|
||||
// 设置商户编号
|
||||
param.setMerNo(miFaPayProperties.getMerNo());
|
||||
|
||||
String url = miFaPayProperties.getGatewayBaseUrl() + PLACE_ORDER_PATH;
|
||||
|
||||
@ -78,28 +80,61 @@ public class MiFaPayService {
|
||||
.block();
|
||||
|
||||
// 非生产环境打印响应日志
|
||||
if (!Objects.equals(active, "prod")) {
|
||||
log.warn("MiFaPay Response: {}", JacksonUtils.toJson(response));
|
||||
}
|
||||
|
||||
// 验证响应签名
|
||||
if (response != null && response.isSuccess() && response.getData() != null) {
|
||||
// boolean validSign = PayMaxUtils.validSignRsa(
|
||||
// response.getData(),
|
||||
// response.getSign(),
|
||||
// miFaPayProperties.getPlatformRsaPublicKey()
|
||||
// );
|
||||
// if (!validSign) {
|
||||
// log.error("MiFaPay response sign verification failed!");
|
||||
// }
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* MiFaPay请求体结构
|
||||
*/
|
||||
if (!Objects.equals(active, "prod")) {
|
||||
log.warn("MiFaPay Response: {}", JacksonUtils.toJson(response));
|
||||
}
|
||||
|
||||
verifySuccessfulResponse(response);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public String getNotifyUrl() {
|
||||
validateRequiredValue("notifyUrl", miFaPayProperties.getNotifyUrl());
|
||||
return miFaPayProperties.getNotifyUrl();
|
||||
}
|
||||
|
||||
private void verifySuccessfulResponse(MiFaPayResponseCO response) {
|
||||
if (response == null || !response.isSuccess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
validateRequiredValue("response.data", response.getData());
|
||||
validateRequiredValue("response.sign", response.getSign());
|
||||
|
||||
if (StringUtils.isNotBlank(response.getMerAccount())
|
||||
&& !Objects.equals(response.getMerAccount(), miFaPayProperties.getMerAccount())) {
|
||||
throw new IllegalStateException("MiFaPay response merAccount mismatch");
|
||||
}
|
||||
|
||||
boolean validSign = PayMaxUtils.validSignRsa(
|
||||
response.getData(),
|
||||
response.getSign(),
|
||||
miFaPayProperties.getPlatformRsaPublicKey()
|
||||
);
|
||||
if (!validSign) {
|
||||
throw new IllegalStateException("MiFaPay response signature verification failed");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateRequiredConfig() {
|
||||
validateRequiredValue("merAccount", miFaPayProperties.getMerAccount());
|
||||
validateRequiredValue("merNo", miFaPayProperties.getMerNo());
|
||||
validateRequiredValue("gatewayBaseUrl", miFaPayProperties.getGatewayBaseUrl());
|
||||
validateRequiredValue("rsaPrivateKey", miFaPayProperties.getRsaPrivateKey());
|
||||
validateRequiredValue("platformRsaPublicKey", miFaPayProperties.getPlatformRsaPublicKey());
|
||||
validateRequiredValue("notifyUrl", miFaPayProperties.getNotifyUrl());
|
||||
}
|
||||
|
||||
private void validateRequiredValue(String fieldName, String value) {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
throw new IllegalStateException("MiFaPay config missing: " + fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MiFaPay请求体结构
|
||||
*/
|
||||
@Data
|
||||
public static class MiFaPayRequest {
|
||||
/**
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
package com.red.circle.order.app.dto.clientobject.pay;
|
||||
|
||||
import com.red.circle.framework.dto.DTO;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 支付单状态.
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PayOrderStatusCO extends DTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 站内支付单号.
|
||||
*/
|
||||
private String orderId;
|
||||
|
||||
/**
|
||||
* 第三方平台订单号.
|
||||
*/
|
||||
private String tradeNo;
|
||||
|
||||
/**
|
||||
* 当前支付状态.
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 是否支付成功.
|
||||
*/
|
||||
private Boolean success;
|
||||
|
||||
/**
|
||||
* 是否已进入终态.
|
||||
*/
|
||||
private Boolean finished;
|
||||
|
||||
/**
|
||||
* 失败或挂起原因.
|
||||
*/
|
||||
private String reason;
|
||||
|
||||
/**
|
||||
* 厂商编码.
|
||||
*/
|
||||
private String factoryCode;
|
||||
|
||||
/**
|
||||
* 厂商渠道编码.
|
||||
*/
|
||||
private String factoryChannelCode;
|
||||
|
||||
/**
|
||||
* 币种.
|
||||
*/
|
||||
private String currency;
|
||||
|
||||
/**
|
||||
* 金额.
|
||||
*/
|
||||
private BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 最后更新时间.
|
||||
*/
|
||||
private Timestamp updateTime;
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.red.circle.order.app.dto.cmd;
|
||||
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.io.Serial;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 支付单状态查询.
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PayOrderStatusCmd extends AppExtCommand {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 站内支付单号.
|
||||
*/
|
||||
@NotBlank(message = "orderId required.")
|
||||
private String orderId;
|
||||
}
|
||||
@ -2,14 +2,16 @@ package com.red.circle.order.app.service;
|
||||
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.common.business.dto.cmd.IdStringCmd;
|
||||
import com.red.circle.order.app.dto.clientobject.PayMaxResponseCO;
|
||||
import com.red.circle.order.app.dto.clientobject.PayerMaxResponseV2CO;
|
||||
import com.red.circle.order.app.dto.clientobject.PurchaseReceiptCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.app.dto.cmd.AbstractPurchaseCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderReceiptCmd;
|
||||
import java.util.Map;
|
||||
import com.red.circle.order.app.dto.clientobject.PayMaxResponseCO;
|
||||
import com.red.circle.order.app.dto.clientobject.PayerMaxResponseV2CO;
|
||||
import com.red.circle.order.app.dto.clientobject.PurchaseReceiptCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PayOrderStatusCO;
|
||||
import com.red.circle.order.app.dto.clientobject.pay.PlaceAnOrderResponseCO;
|
||||
import com.red.circle.order.app.dto.cmd.AbstractPurchaseCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayOrderStatusCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderCmd;
|
||||
import com.red.circle.order.app.dto.cmd.PayPlaceAnOrderReceiptCmd;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 内购产品服务.
|
||||
@ -30,10 +32,15 @@ public interface InAppPurchaseProductService {
|
||||
|
||||
PayMaxResponseCO payerMaxServerNoticeRefundNotice(byte[] body);
|
||||
|
||||
PlaceAnOrderResponseCO placeAnOrder(PayPlaceAnOrderCmd cmd);
|
||||
|
||||
@Deprecated
|
||||
PlaceAnOrderResponseCO payReceipt(PayPlaceAnOrderReceiptCmd cmd);
|
||||
PlaceAnOrderResponseCO placeAnOrder(PayPlaceAnOrderCmd cmd);
|
||||
|
||||
/**
|
||||
* 查询支付单状态.
|
||||
*/
|
||||
PayOrderStatusCO orderStatus(PayOrderStatusCmd cmd);
|
||||
|
||||
@Deprecated
|
||||
PlaceAnOrderResponseCO payReceipt(PayPlaceAnOrderReceiptCmd cmd);
|
||||
|
||||
@Deprecated
|
||||
Object collectionReceipt(IdStringCmd cmd);
|
||||
|
||||
@ -36,8 +36,13 @@ public class MiFaPayProperties {
|
||||
*/
|
||||
private String rsaPrivateKey;
|
||||
|
||||
/**
|
||||
* 平台公钥(用于验签)
|
||||
*/
|
||||
private String platformRsaPublicKey;
|
||||
}
|
||||
/**
|
||||
* 平台公钥(用于验签)
|
||||
*/
|
||||
private String platformRsaPublicKey;
|
||||
|
||||
/**
|
||||
* 支付结果异步通知地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
}
|
||||
|
||||
@ -22,22 +22,24 @@ import org.springframework.stereotype.Service;
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class InAppPurchaseCollectionReceiptServiceImpl implements
|
||||
InAppPurchaseCollectionReceiptService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
public class InAppPurchaseCollectionReceiptServiceImpl implements
|
||||
InAppPurchaseCollectionReceiptService {
|
||||
|
||||
private static final String ID_FIELD = "_id";
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
@Override
|
||||
public void create(InAppPurchaseCollectionReceipt receipt) {
|
||||
mongoTemplate.save(receipt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(InAppPurchaseCollectionReceipt receipt) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(receipt.getId())),
|
||||
new Update()
|
||||
.set("acceptUserId", receipt.getAcceptUserId())
|
||||
.set("amount", receipt.getAmount())
|
||||
@Override
|
||||
public void update(InAppPurchaseCollectionReceipt receipt) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(receipt.getId())),
|
||||
new Update()
|
||||
.set("acceptUserId", receipt.getAcceptUserId())
|
||||
.set("amount", receipt.getAmount())
|
||||
.set("amountUsd", receipt.getAmountUsd())
|
||||
.set("usdExchangeRate", receipt.getUsdExchangeRate())
|
||||
.set("currency", receipt.getCurrency())
|
||||
@ -50,32 +52,32 @@ public class InAppPurchaseCollectionReceiptServiceImpl implements
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(String id, Long operationUserId) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("status", InAppPurchaseCollectionReceiptStatus.CLOSE)
|
||||
@Override
|
||||
public void close(String id, Long operationUserId) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("status", InAppPurchaseCollectionReceiptStatus.CLOSE)
|
||||
.set("updateUser", operationUserId),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatusSuccess(String id) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("status", InAppPurchaseCollectionReceiptStatus.SUCCESS)
|
||||
@Override
|
||||
public void updateStatusSuccess(String id) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("status", InAppPurchaseCollectionReceiptStatus.SUCCESS)
|
||||
.set("lockTime", TimestampUtils.now()),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatusSuccessFail(String id) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("status", InAppPurchaseCollectionReceiptStatus.FAIL)
|
||||
@Override
|
||||
public void updateStatusSuccessFail(String id) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("status", InAppPurchaseCollectionReceiptStatus.FAIL)
|
||||
.set("lockTime", TimestampUtils.now()),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
@ -84,14 +86,14 @@ public class InAppPurchaseCollectionReceiptServiceImpl implements
|
||||
public List<InAppPurchaseCollectionReceipt> list(
|
||||
InAppPurchaseCollectionReceiptQuery query) {
|
||||
|
||||
Criteria criteria = StringUtils.isBlank(query.getSysOrigin())
|
||||
? new Criteria()
|
||||
: Criteria.where("sysOrigin").is(query.getSysOrigin());
|
||||
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
query.setLastId(null);
|
||||
criteria.and("id").is(query.getId());
|
||||
}
|
||||
Criteria criteria = StringUtils.isBlank(query.getSysOrigin())
|
||||
? new Criteria()
|
||||
: Criteria.where("sysOrigin").is(query.getSysOrigin());
|
||||
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
query.setLastId(null);
|
||||
criteria.and(ID_FIELD).is(query.getId());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(query.getStatus())) {
|
||||
criteria.and("status").is(query.getStatus());
|
||||
@ -112,32 +114,32 @@ public class InAppPurchaseCollectionReceiptServiceImpl implements
|
||||
);
|
||||
}
|
||||
|
||||
if (Objects.nonNull(query.getLastId())) {
|
||||
criteria.and("id").lt(query.getLastId());
|
||||
}
|
||||
if (Objects.nonNull(query.getLastId())) {
|
||||
criteria.and(ID_FIELD).lt(query.getLastId());
|
||||
}
|
||||
|
||||
if (Objects.isNull(query.getLimit())) {
|
||||
query.setLimit(PageConstant.DEFAULT_LIMIT_SIZE);
|
||||
}
|
||||
|
||||
return mongoTemplate.find(Query.query(criteria)
|
||||
.with(Sort.by(Sort.Order.desc("id")))
|
||||
.limit(query.getLimit()),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
return mongoTemplate.find(Query.query(criteria)
|
||||
.with(Sort.by(Sort.Order.desc(ID_FIELD)))
|
||||
.limit(query.getLimit()),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InAppPurchaseCollectionReceipt getById(String id) {
|
||||
return mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
@Override
|
||||
public InAppPurchaseCollectionReceipt getById(String id) {
|
||||
return mongoTemplate.findOne(Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lockTime(String id, long minute) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("lockTime", TimestampUtils.nowPlusMinutes(minute)),
|
||||
@Override
|
||||
public void lockTime(String id, long minute) {
|
||||
mongoTemplate.updateFirst(Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.set("updateTime", TimestampUtils.now())
|
||||
.set("lockTime", TimestampUtils.nowPlusMinutes(minute)),
|
||||
InAppPurchaseCollectionReceipt.class);
|
||||
}
|
||||
|
||||
|
||||
@ -33,20 +33,22 @@ import org.springframework.stereotype.Service;
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsService {
|
||||
|
||||
private static final String ID_FIELD = "_id";
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
@Override
|
||||
public void create(InAppPurchaseDetails inAppPurchaseDetails) {
|
||||
mongoTemplate.insert(inAppPurchaseDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InAppPurchaseDetails getById(String id) {
|
||||
return mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)),
|
||||
InAppPurchaseDetails.class);
|
||||
}
|
||||
@Override
|
||||
public InAppPurchaseDetails getById(String id) {
|
||||
return mongoTemplate.findOne(Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
InAppPurchaseDetails.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InAppPurchaseDetails getByOrderId(String orderId) {
|
||||
@ -56,34 +58,34 @@ public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsPayNotice(String id, String eventId, String noticeType) {
|
||||
return mongoTemplate.exists(Query.query(
|
||||
Criteria.where("id").is(id)
|
||||
.elemMatch(Criteria.where("eventId").is(eventId).is("noticeType").is(noticeType))
|
||||
), InAppPurchaseDetails.class);
|
||||
}
|
||||
public boolean existsPayNotice(String id, String eventId, String noticeType) {
|
||||
return mongoTemplate.exists(Query.query(
|
||||
Criteria.where(ID_FIELD).is(id)
|
||||
.elemMatch(Criteria.where("eventId").is(eventId).is("noticeType").is(noticeType))
|
||||
), InAppPurchaseDetails.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsPayNoticeByEventId(String id, String eventId) {
|
||||
return mongoTemplate.exists(Query.query(
|
||||
Criteria.where("id").is(id).elemMatch(Criteria.where("eventId").is(eventId))
|
||||
), InAppPurchaseDetails.class);
|
||||
}
|
||||
public boolean existsPayNoticeByEventId(String id, String eventId) {
|
||||
return mongoTemplate.exists(Query.query(
|
||||
Criteria.where(ID_FIELD).is(id).elemMatch(Criteria.where("eventId").is(eventId))
|
||||
), InAppPurchaseDetails.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsPayNoticeByNoticeType(String id, String noticeType) {
|
||||
return mongoTemplate.exists(Query.query(
|
||||
Criteria.where("id").is(id).elemMatch(Criteria.where("noticeType").is(noticeType))
|
||||
), InAppPurchaseDetails.class);
|
||||
}
|
||||
public boolean existsPayNoticeByNoticeType(String id, String noticeType) {
|
||||
return mongoTemplate.exists(Query.query(
|
||||
Criteria.where(ID_FIELD).is(id).elemMatch(Criteria.where("noticeType").is(noticeType))
|
||||
), InAppPurchaseDetails.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPayNotices(String id, InAppPurchaseEventNotice payNotice) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.push("payNotices", payNotice)
|
||||
.set("updateTime", TimestampUtils.now()),
|
||||
public void addPayNotices(String id, InAppPurchaseEventNotice payNotice) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.push("payNotices", payNotice)
|
||||
.set("updateTime", TimestampUtils.now()),
|
||||
InAppPurchaseDetails.class
|
||||
);
|
||||
}
|
||||
@ -100,12 +102,12 @@ public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatus(String id, InAppPurchaseStatus status) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.set("status", status)
|
||||
.push("statusSteps", new InAppPurchaseStatusStep()
|
||||
public void updateStatus(String id, InAppPurchaseStatus status) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.set("status", status)
|
||||
.push("statusSteps", new InAppPurchaseStatusStep()
|
||||
.setStatus(status)
|
||||
.setCreateTime(TimestampUtils.now())
|
||||
)
|
||||
@ -115,12 +117,12 @@ public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateStatusReason(String id, InAppPurchaseStatus status, String reason) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.set("status", status)
|
||||
.set("reason", reason)
|
||||
public void updateStatusReason(String id, InAppPurchaseStatus status, String reason) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.set("status", status)
|
||||
.set("reason", reason)
|
||||
.push("statusSteps", new InAppPurchaseStatusStep()
|
||||
.setStatus(status)
|
||||
.setCreateTime(TimestampUtils.now())
|
||||
@ -138,13 +140,13 @@ public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsServ
|
||||
}
|
||||
|
||||
// 各大云厂商mongo版本差异和自定义特性在属性字段上可能存在支持上会出现偏差,不允许字段出现. or $特殊属性
|
||||
String newKey = key.replaceAll("\\.", "_").replaceAll("\\$", "_");
|
||||
details.getMetadata().put(newKey, val);
|
||||
return mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where("id").is(details.getId())
|
||||
.and("version").is(details.getVersion())),
|
||||
new Update()
|
||||
.set("metadata", details.getMetadata())
|
||||
String newKey = key.replaceAll("\\.", "_").replaceAll("\\$", "_");
|
||||
details.getMetadata().put(newKey, val);
|
||||
return mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where(ID_FIELD).is(details.getId())
|
||||
.and("version").is(details.getVersion())),
|
||||
new Update()
|
||||
.set("metadata", details.getMetadata())
|
||||
.set("version", details.getVersion() + 1)
|
||||
.set("updateTime", TimestampUtils.now()),
|
||||
InAppPurchaseDetails.class
|
||||
@ -154,12 +156,12 @@ public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsServ
|
||||
@Override
|
||||
public List<InAppPurchaseDetails> list(InAppPurchaseDetailsQuery query) {
|
||||
|
||||
Criteria criteria = new Criteria();
|
||||
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
query.setLastId(null);
|
||||
criteria.and("id").is(query.getId());
|
||||
}
|
||||
Criteria criteria = new Criteria();
|
||||
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
query.setLastId(null);
|
||||
criteria.and(ID_FIELD).is(query.getId());
|
||||
}
|
||||
if (Objects.nonNull(query.getReceiptType())) {
|
||||
criteria.and("receiptType").is(query.getReceiptType());
|
||||
}
|
||||
@ -203,27 +205,27 @@ public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsServ
|
||||
);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(query.getLastId())) {
|
||||
criteria.and("id").lt(query.getLastId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(query.getLastId())) {
|
||||
criteria.and(ID_FIELD).lt(query.getLastId());
|
||||
}
|
||||
|
||||
if (Objects.isNull(query.getLimit()) || query.getLimit() <= 0) {
|
||||
query.setLimit(PageConstant.DEFAULT_LIMIT_SIZE);
|
||||
}
|
||||
|
||||
return mongoTemplate
|
||||
.find(Query.query(criteria)
|
||||
.with(Sort.by(Sort.Order.desc("id")))
|
||||
.limit(query.getLimit()), InAppPurchaseDetails.class);
|
||||
}
|
||||
return mongoTemplate
|
||||
.find(Query.query(criteria)
|
||||
.with(Sort.by(Sort.Order.desc(ID_FIELD)))
|
||||
.limit(query.getLimit()), InAppPurchaseDetails.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> statistics(InAppPurchaseDetailsQuery query) {
|
||||
Criteria criteria = new Criteria();
|
||||
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
criteria.and("id").is(query.getId());
|
||||
}
|
||||
Criteria criteria = new Criteria();
|
||||
|
||||
if (StringUtils.isNotBlank(query.getId())) {
|
||||
criteria.and(ID_FIELD).is(query.getId());
|
||||
}
|
||||
if (Objects.nonNull(query.getReceiptType())) {
|
||||
criteria.and("receiptType").is(query.getReceiptType());
|
||||
}
|
||||
@ -336,12 +338,12 @@ public class InAppPurchaseDetailsServiceImpl implements InAppPurchaseDetailsServ
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMetadata(String id, Map<String, String> metadata) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where("id").is(id)),
|
||||
new Update()
|
||||
.set("metadata", metadata),
|
||||
InAppPurchaseDetails.class
|
||||
public void updateMetadata(String id, Map<String, String> metadata) {
|
||||
mongoTemplate.updateFirst(
|
||||
Query.query(Criteria.where(ID_FIELD).is(id)),
|
||||
new Update()
|
||||
.set("metadata", metadata),
|
||||
InAppPurchaseDetails.class
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
package com.red.circle.order.infra.database.rds.dao.order;
|
||||
|
||||
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePay;
|
||||
|
||||
/**
|
||||
* Web支付预下单 Mapper.
|
||||
*/
|
||||
public interface OrderUserPurchasePayDAO extends BaseDAO<OrderUserPurchasePay> {
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.red.circle.order.infra.database.rds.dao.order;
|
||||
|
||||
import com.red.circle.framework.mybatis.dao.BaseDAO;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePayNotice;
|
||||
|
||||
/**
|
||||
* Web支付通知明细 Mapper.
|
||||
*/
|
||||
public interface OrderUserPurchasePayNoticeDAO extends BaseDAO<OrderUserPurchasePayNotice> {
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
package com.red.circle.order.infra.database.rds.entity.order;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* Web支付预下单记录.
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("order_user_purchase_pay")
|
||||
public class OrderUserPurchasePay implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.INPUT)
|
||||
private Long id;
|
||||
|
||||
@TableField("evn")
|
||||
private String evn;
|
||||
|
||||
@TableField("sys_origin")
|
||||
private String sysOrigin;
|
||||
|
||||
@TableField("user_id")
|
||||
private Long userId;
|
||||
|
||||
@TableField("factory_code")
|
||||
private String factoryCode;
|
||||
|
||||
@TableField("factory_order_id")
|
||||
private String factoryOrderId;
|
||||
|
||||
@TableField("reference_id")
|
||||
private String referenceId;
|
||||
|
||||
@TableField("receipt_type")
|
||||
private String receiptType;
|
||||
|
||||
@TableField("payment_channel")
|
||||
private String paymentChannel;
|
||||
|
||||
@TableField("factory_channel")
|
||||
private String factoryChannel;
|
||||
|
||||
@TableField("product_code")
|
||||
private String productCode;
|
||||
|
||||
@TableField("product_content")
|
||||
private String productContent;
|
||||
|
||||
@TableField("product_descriptor")
|
||||
private String productDescriptor;
|
||||
|
||||
@TableField("payment_unit")
|
||||
private String paymentUnit;
|
||||
|
||||
@TableField("payment_amount")
|
||||
private BigDecimal paymentAmount;
|
||||
|
||||
@TableField("compute_usd_amount")
|
||||
private BigDecimal computeUsdAmount;
|
||||
|
||||
@TableField("compute_usd_rate")
|
||||
private String computeUsdRate;
|
||||
|
||||
@TableField("give_away_content")
|
||||
private String giveAwayContent;
|
||||
|
||||
@TableField("country_id")
|
||||
private Long countryId;
|
||||
|
||||
@TableField("country_code")
|
||||
private String countryCode;
|
||||
|
||||
@TableField("pay_country_id")
|
||||
private Long payCountryId;
|
||||
|
||||
@TableField("pay_status")
|
||||
private String payStatus;
|
||||
|
||||
@TableField("reason")
|
||||
private String reason;
|
||||
|
||||
@TableField("refund_status")
|
||||
private String refundStatus;
|
||||
|
||||
@TableField("receipt_details_id")
|
||||
private Long receiptDetailsId;
|
||||
|
||||
@TableField("create_time")
|
||||
private Timestamp createTime;
|
||||
|
||||
@TableField("update_time")
|
||||
private Timestamp updateTime;
|
||||
|
||||
@TableField("create_user")
|
||||
private Long createUser;
|
||||
|
||||
@TableField("update_user")
|
||||
private Long updateUser;
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.red.circle.order.infra.database.rds.entity.order;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* Web支付通知明细.
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("order_user_purchase_pay_notice")
|
||||
public class OrderUserPurchasePayNotice extends TimestampBaseEntity {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
@TableField("purchase_pay_id")
|
||||
private Long purchasePayId;
|
||||
|
||||
@TableField("event_id")
|
||||
private String eventId;
|
||||
|
||||
@TableField("notice_type")
|
||||
private String noticeType;
|
||||
|
||||
@TableField("notice_data")
|
||||
private String noticeData;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.red.circle.order.infra.database.rds.service.order;
|
||||
|
||||
import com.red.circle.framework.mybatis.service.BaseService;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePayNotice;
|
||||
|
||||
/**
|
||||
* Web支付通知明细服务.
|
||||
*/
|
||||
public interface OrderUserPurchasePayNoticeService extends BaseService<OrderUserPurchasePayNotice> {
|
||||
|
||||
/**
|
||||
* 保存通知.
|
||||
*/
|
||||
void addNotice(Long purchasePayId, String eventId, String noticeType, Object noticeData,
|
||||
Long operationUserId);
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.red.circle.order.infra.database.rds.service.order;
|
||||
|
||||
import com.red.circle.framework.mybatis.service.BaseService;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePay;
|
||||
|
||||
/**
|
||||
* Web支付预下单服务.
|
||||
*/
|
||||
public interface OrderUserPurchasePayService extends BaseService<OrderUserPurchasePay> {
|
||||
|
||||
/**
|
||||
* 标记支付成功.
|
||||
*/
|
||||
void updateSuccess(Long id);
|
||||
|
||||
/**
|
||||
* 标记支付失败.
|
||||
*/
|
||||
void updateFail(Long id, String reason);
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.red.circle.order.infra.database.rds.service.order.impl;
|
||||
|
||||
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||
import com.red.circle.order.infra.database.rds.dao.order.OrderUserPurchasePayNoticeDAO;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePayNotice;
|
||||
import com.red.circle.order.infra.database.rds.service.order.OrderUserPurchasePayNoticeService;
|
||||
import com.red.circle.tool.core.json.JacksonUtils;
|
||||
import java.util.Objects;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Web支付通知明细服务实现.
|
||||
*/
|
||||
@Service
|
||||
public class OrderUserPurchasePayNoticeServiceImpl
|
||||
extends BaseServiceImpl<OrderUserPurchasePayNoticeDAO, OrderUserPurchasePayNotice>
|
||||
implements OrderUserPurchasePayNoticeService {
|
||||
|
||||
@Override
|
||||
public void addNotice(Long purchasePayId, String eventId, String noticeType, Object noticeData,
|
||||
Long operationUserId) {
|
||||
OrderUserPurchasePayNotice notice = new OrderUserPurchasePayNotice()
|
||||
.setPurchasePayId(purchasePayId)
|
||||
.setEventId(Objects.toString(eventId, ""))
|
||||
.setNoticeType(Objects.toString(noticeType, ""))
|
||||
.setNoticeData(JacksonUtils.toJson(noticeData));
|
||||
notice.setCreateUser(operationUserId);
|
||||
notice.setUpdateUser(operationUserId);
|
||||
save(notice);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.red.circle.order.infra.database.rds.service.order.impl;
|
||||
|
||||
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||
import com.red.circle.order.infra.database.rds.dao.order.OrderUserPurchasePayDAO;
|
||||
import com.red.circle.order.infra.database.rds.entity.order.OrderUserPurchasePay;
|
||||
import com.red.circle.order.infra.database.rds.service.order.OrderUserPurchasePayService;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Web支付预下单服务实现.
|
||||
*/
|
||||
@Service
|
||||
public class OrderUserPurchasePayServiceImpl
|
||||
extends BaseServiceImpl<OrderUserPurchasePayDAO, OrderUserPurchasePay>
|
||||
implements OrderUserPurchasePayService {
|
||||
|
||||
private static final String PAY_STATUS_SUCCESSFUL = "SUCCESSFUL";
|
||||
private static final String PAY_STATUS_FAIL = "FAIL";
|
||||
|
||||
@Override
|
||||
public void updateSuccess(Long id) {
|
||||
update()
|
||||
.set(OrderUserPurchasePay::getPayStatus, PAY_STATUS_SUCCESSFUL)
|
||||
.set(OrderUserPurchasePay::getReason, "")
|
||||
.set(OrderUserPurchasePay::getUpdateTime, TimestampUtils.now())
|
||||
.eq(OrderUserPurchasePay::getId, id)
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFail(Long id, String reason) {
|
||||
update()
|
||||
.set(OrderUserPurchasePay::getPayStatus, PAY_STATUS_FAIL)
|
||||
.set(OrderUserPurchasePay::getReason, reason)
|
||||
.set(OrderUserPurchasePay::getUpdateTime, TimestampUtils.now())
|
||||
.eq(OrderUserPurchasePay::getId, id)
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,14 @@
|
||||
package com.red.circle.other.app.command.gift.query;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.other.app.dto.clientobject.gift.ActivityGiftCO;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.database.cache.service.other.BannerCacheService;
|
||||
package com.red.circle.other.app.command.gift.query;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.other.app.dto.clientobject.gift.ActivityGiftCO;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.cache.service.other.BannerCacheService;
|
||||
import com.red.circle.other.infra.database.mongo.entity.sys.ActivityConfig;
|
||||
import com.red.circle.other.infra.database.mongo.service.sys.ActivityConfigService;
|
||||
import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig;
|
||||
@ -36,9 +37,10 @@ public class ActivityGiftListQryExe {
|
||||
|
||||
private final ActivityConfigService activityConfigService;
|
||||
private final GiftConfigService giftConfigService;
|
||||
private final BannerConfigService bannerConfigService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final UserRegionGateway userRegionGateway;
|
||||
private final BannerConfigService bannerConfigService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final UserRegionGateway userRegionGateway;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
public List<ActivityGiftCO> execute(AppExtCommand cmd) {
|
||||
// 获取进行中的活动
|
||||
@ -78,12 +80,13 @@ public class ActivityGiftListQryExe {
|
||||
|
||||
Map<Long, BannerConfig> bannerUrlMap;
|
||||
if (!bannerIds.isEmpty()) {
|
||||
LambdaQueryWrapper<BannerConfig> query = Wrappers.<BannerConfig>lambdaQuery()
|
||||
.in(BannerConfig::getId, bannerIds);
|
||||
bannerUrlMap = bannerConfigService.list(query).stream()
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getRegions()) || bannerCache.getRegions().contains(regionId))
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getCountryCode()) || bannerCache.getCountryCode().contains(countryCode))
|
||||
.collect(Collectors.toMap(BannerConfig::getId, e -> e, (u1, u2) -> u1));
|
||||
LambdaQueryWrapper<BannerConfig> query = Wrappers.<BannerConfig>lambdaQuery()
|
||||
.in(BannerConfig::getId, bannerIds);
|
||||
bannerUrlMap = bannerConfigService.list(query).stream()
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getRegions()) || bannerCache.getRegions().contains(regionId))
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getCountryCode())
|
||||
|| countryCodeAliasSupport.containsCode(bannerCache.getCountryCode(), countryCode))
|
||||
.collect(Collectors.toMap(BannerConfig::getId, e -> e, (u1, u2) -> u1));
|
||||
} else {
|
||||
bannerUrlMap = new HashMap<>();
|
||||
}
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
package com.red.circle.other.app.command.room.query;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.red.circle.common.business.dto.cmd.app.AppFlowCmd;
|
||||
import com.red.circle.common.business.enums.SVIPLevelEnum;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.nacos.common.utils.CollectionUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.red.circle.common.business.dto.cmd.app.AppFlowCmd;
|
||||
import com.red.circle.common.business.enums.SVIPLevelEnum;
|
||||
import com.red.circle.other.app.common.room.RoomVoiceProfileCommon;
|
||||
import com.red.circle.other.app.convertor.live.RoomProfileAppConvertor;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomBrowseRecordsV2CO;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserSVipGateway;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.RankQueenCount;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomBrowseRecordsV2CO;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserSVipGateway;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.RankQueenCount;
|
||||
import com.red.circle.other.infra.database.mongo.entity.activity.RankQueenType;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile;
|
||||
@ -37,10 +38,11 @@ import java.util.stream.Stream;
|
||||
@AllArgsConstructor
|
||||
public class RoomGiftListQueryExe {
|
||||
|
||||
private final UserSVipGateway userSVipGateway;
|
||||
private final RankCountService rankCountService;
|
||||
private final UserRegionGateway userRegionGateway;
|
||||
private final RoomProfileAppConvertor roomProfileAppConvertor;
|
||||
private final UserSVipGateway userSVipGateway;
|
||||
private final RankCountService rankCountService;
|
||||
private final UserRegionGateway userRegionGateway;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
private final RoomProfileAppConvertor roomProfileAppConvertor;
|
||||
private final ActiveVoiceRoomService activeVoiceRoomService;
|
||||
private final RoomVoiceProfileCommon roomVoiceProfileCommon;
|
||||
private final RoomUserBlacklistService roomUserBlacklistService;
|
||||
@ -183,7 +185,8 @@ public class RoomGiftListQueryExe {
|
||||
return assemblyRoomVoiceProfile(activeVoiceRooms, cmd);
|
||||
}
|
||||
|
||||
List<String> excludeCountryCodes = List.of("SA", "AE", "EG", "MA", "US");
|
||||
List<String> excludeCountryCodes = new ArrayList<>(
|
||||
countryCodeAliasSupport.expandCodes(List.of("SA", "AE", "EG", "MA", "US")));
|
||||
List<RoomBrowseRecordsV2CO> roomVoiceProfiles = Lists.newArrayList();
|
||||
if (CollectionUtils.isEmpty(activeVoiceRooms)) {
|
||||
List<RoomVoiceProfileCO> roomVoiceProfileCos = roomVoiceProfileCommon.listRoomVoiceProfilesV2(
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
package com.red.circle.other.app.command.room.query;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.Gson;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.common.business.enums.SVIPLevelEnum;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.Gson;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.common.business.enums.SVIPLevelEnum;
|
||||
import com.red.circle.live.inner.endpoint.LiveMicClient;
|
||||
import com.red.circle.other.app.common.room.RoomVoiceProfileCommon;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
|
||||
import com.red.circle.other.app.service.game.GameLudoService;
|
||||
import com.red.circle.other.app.service.room.RocketStatusCacheService;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserSVipGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.domain.rocket.RocketStatus;
|
||||
import com.red.circle.other.infra.database.cache.service.user.RegionRoomCacheService;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserSVipGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.domain.rocket.RocketStatus;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.cache.service.user.RegionRoomCacheService;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomUserBlacklist;
|
||||
@ -60,15 +61,16 @@ public class RoomVoiceDiscoverQryExe {
|
||||
private final RegionRoomCacheService regionRoomCacheService;
|
||||
private final LiveMicClient liveMicClient;
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final RocketStatusCacheService rocketStatusCacheService;
|
||||
private final GameLudoService gameLudoService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final RocketStatusCacheService rocketStatusCacheService;
|
||||
private final GameLudoService gameLudoService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
private static final String EMPTY_ROOM_CACHE_KEY = "empty_room_cache:*";
|
||||
|
||||
// 区域隔离常量 - 与ActiveVoiceRoomServiceImpl保持一致
|
||||
private static final Set<String> TR_REGIONS = Set.of("TR");
|
||||
private static final Set<String> SA_REGIONS = Set.of("BD","SA", "IN", "PK");
|
||||
// 区域隔离常量 - 与ActiveVoiceRoomServiceImpl保持一致
|
||||
private static final Set<String> TR_REGIONS = Set.of("TR");
|
||||
private static final Set<String> SA_REGIONS = Set.of("BD","SA", "IN", "PK");
|
||||
private static final Set<String> AR_REGIONS = Set.of("AE", "AR", "BH", "DJ", "DZ", "EG", "EY", "ER", "IL", "IQ", "JO", "KM", "KW", "LB", "LY", "MA", "MR", "OM", "PS", "QA", "SD", "SO", "SS", "SY", "TD", "TN", "YE");
|
||||
private static final Set<String> OTHER_REGIONS = Set.of("OTHER", "PH", "ID", "GH", "IR", "AF", "NG", "DE", "MYS", "TM", "AZ", "NP");
|
||||
|
||||
@ -261,7 +263,8 @@ public class RoomVoiceDiscoverQryExe {
|
||||
return emptyRooms.stream()
|
||||
.filter(room -> Objects.equals(sysOrigin, room.getSysOrigin()) &&
|
||||
(isAllRegion || shouldShowRoom(region, room.getRegion())) &&
|
||||
(!SA_REGIONS.contains(region) || userCountryCode == null || userCountryCode.equals(room.getCountryCode())))
|
||||
(!SA_REGIONS.contains(region) || userCountryCode == null
|
||||
|| countryCodeAliasSupport.matches(userCountryCode, room.getCountryCode())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
package com.red.circle.other.app.command.sys.query;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
package com.red.circle.other.app.command.sys.query;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||
import com.red.circle.order.inner.endpoint.OrderPurchaseHistoryClient;
|
||||
import com.red.circle.other.app.convertor.sys.SysConfigAppConvertor;
|
||||
import com.red.circle.other.app.dto.clientobject.sys.BannerCO;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.database.cache.entity.sys.BannerCache;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.cache.entity.sys.BannerCache;
|
||||
import com.red.circle.other.infra.database.cache.service.other.BannerCacheService;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.BannerConfig;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.BannerConfigService;
|
||||
@ -36,9 +37,10 @@ public class BannerQryExe {
|
||||
private final UserRegionGateway userRegionGateway;
|
||||
private final BannerCacheService bannerCacheService;
|
||||
private final BannerConfigService bannerConfigService;
|
||||
private final SysConfigAppConvertor sysConfigAppConvertor;
|
||||
private final OrderPurchaseHistoryClient orderPurchaseHistoryClient;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final SysConfigAppConvertor sysConfigAppConvertor;
|
||||
private final OrderPurchaseHistoryClient orderPurchaseHistoryClient;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
public List<BannerCO> execute(AppExtCommand cmd, List<String> typeList) {
|
||||
UserProfile userProfile = userProfileGateway.getByUserId(cmd.requiredReqUserId());
|
||||
@ -55,10 +57,11 @@ public class BannerQryExe {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
return sysConfigAppConvertor.toListBannerCache(configs);
|
||||
}).stream()
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getRegions()) || bannerCache.getRegions().contains(regionId))
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getCountryCode()) || bannerCache.getCountryCode().contains(countryCode))
|
||||
.toList();
|
||||
}).stream()
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getRegions()) || bannerCache.getRegions().contains(regionId))
|
||||
.filter(bannerCache -> StringUtils.isBlank(bannerCache.getCountryCode())
|
||||
|| countryCodeAliasSupport.containsCode(bannerCache.getCountryCode(), countryCode))
|
||||
.toList();
|
||||
return sysConfigAppConvertor.toListBannerCO(list);
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
package com.red.circle.other.app.command.sys.query;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.red.circle.other.app.dto.clientobject.sys.CountryCodeCO;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
|
||||
import com.red.circle.other.app.dto.clientobject.sys.CountryCodeCO;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.SysCountryCodeService;
|
||||
|
||||
@ -37,15 +38,19 @@ public class SysCountryOpenTopQryExe {
|
||||
if (Objects.isNull(sysCountryCode)) {
|
||||
return null;
|
||||
}
|
||||
return new CountryCodeCO()
|
||||
.setId(sysCountryCode.getId())
|
||||
.setAlphaTwo(sysCountryCode.getAlphaTwo())
|
||||
.setAlphaThree(sysCountryCode.getAlphaThree())
|
||||
.setCountryName(sysCountryCode.getCountryName())
|
||||
.setAliasName(sysCountryCode.getAliasName())
|
||||
.setNationalFlag(sysCountryCode.getNationalFlag())
|
||||
.setPhonePrefix(sysCountryCode.getPhonePrefix())
|
||||
.setOpen(sysCountryCode.getOpen())
|
||||
return new CountryCodeCO()
|
||||
.setId(sysCountryCode.getId())
|
||||
.setAlphaTwo(sysCountryCode.getAlphaTwo())
|
||||
.setAlphaThree(sysCountryCode.getAlphaThree())
|
||||
.setCountryName(sysCountryCode.getCountryName())
|
||||
.setAliasName(sysCountryCode.getAliasName())
|
||||
.setCountryCodeAliases(CountryCodeAliasUtils.normalizeCodes(
|
||||
CountryCodeAliasUtils.buildMatchCodes(sysCountryCode.getAlphaTwo(),
|
||||
sysCountryCode.getAlphaThree(),
|
||||
CountryCodeAliasUtils.parseAliasCodes(sysCountryCode.getAliasCodes()))))
|
||||
.setNationalFlag(sysCountryCode.getNationalFlag())
|
||||
.setPhonePrefix(sysCountryCode.getPhonePrefix())
|
||||
.setOpen(sysCountryCode.getOpen())
|
||||
.setTop(sysCountryCode.getTop());
|
||||
}
|
||||
|
||||
|
||||
@ -371,10 +371,9 @@ public class GameLuckyGiftCommon {
|
||||
}
|
||||
|
||||
|
||||
private static int getRewardMultiple(GameLuckyGiftParam param, Long rewardAmount) {
|
||||
long payAmount = param.getQuantity() * param.getGift().getGiftCandy().longValue();
|
||||
return (int) (rewardAmount / payAmount);
|
||||
}
|
||||
private static int getRewardMultiple(GameLuckyGiftParam param, Long rewardAmount) {
|
||||
return LuckyGiftMultipleCalculator.calculate(rewardAmount, param.getGift().getGiftCandy());
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽奖.
|
||||
@ -458,10 +457,10 @@ public class GameLuckyGiftCommon {
|
||||
/**
|
||||
* 处理用户连续赠送幸运礼物奖励逻辑
|
||||
*/
|
||||
private void saveLuckGiftCount(GameLuckyGiftParam param, Long awardAmount) {
|
||||
|
||||
long payAmount = param.getQuantity() * param.getGift().getGiftCandy().longValue();
|
||||
int multiple = (int) (awardAmount / payAmount);
|
||||
private void saveLuckGiftCount(GameLuckyGiftParam param, Long awardAmount) {
|
||||
|
||||
long payAmount = param.getQuantity() * param.getGift().getGiftCandy().longValue();
|
||||
int multiple = LuckyGiftMultipleCalculator.calculate(awardAmount, param.getGift().getGiftCandy());
|
||||
|
||||
gameLuckyGiftCountService.save(new GameLuckyGiftCount()
|
||||
.setId(param.getId())
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
package com.red.circle.other.app.common.gift;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
final class LuckyGiftMultipleCalculator {
|
||||
|
||||
private LuckyGiftMultipleCalculator() {
|
||||
}
|
||||
|
||||
static int calculate(Long rewardAmount, BigDecimal giftUnitPrice) {
|
||||
if (rewardAmount == null || rewardAmount <= 0 || giftUnitPrice == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long unitPrice = giftUnitPrice.longValue();
|
||||
if (unitPrice <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) (rewardAmount / unitPrice);
|
||||
}
|
||||
}
|
||||
@ -81,7 +81,8 @@ public class LuckyGiftResultProcessor {
|
||||
}
|
||||
|
||||
UserPropsResourcesDTO avatarFrame = getUserAvatarFrameProps(sendUserProfile);
|
||||
long payAmount = resolvePayAmount(event, giftConfig);
|
||||
BigDecimal giftUnitPrice = resolveGiftUnitPrice(event, giftConfig);
|
||||
long payAmount = resolvePayAmount(event, giftUnitPrice);
|
||||
BigDecimal balanceAfter = BigDecimal.valueOf(Objects.requireNonNullElse(response.getBalanceAfter(), 0L));
|
||||
|
||||
for (LuckyGiftGoClient.LuckyGiftGoDrawResult result : response.getResults()) {
|
||||
@ -91,7 +92,7 @@ public class LuckyGiftResultProcessor {
|
||||
}
|
||||
|
||||
long rewardNum = Objects.requireNonNullElse(result.getRewardNum(), 0L);
|
||||
int multiple = payAmount > 0 && rewardNum > 0 ? (int) (rewardNum / payAmount) : 0;
|
||||
int multiple = LuckyGiftMultipleCalculator.calculate(rewardNum, giftUnitPrice);
|
||||
|
||||
gameLuckyGiftCountService.saveOrUpdate(new GameLuckyGiftCount()
|
||||
.setId(Long.valueOf(result.getId()))
|
||||
@ -121,9 +122,15 @@ public class LuckyGiftResultProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private long resolvePayAmount(GameLuckyGiftBusinessEvent event, GiftConfigDTO giftConfig) {
|
||||
BigDecimal giftPrice = Objects.nonNull(event.getGiftPrice()) ? event.getGiftPrice() : giftConfig.getGiftCandy();
|
||||
return giftPrice.multiply(BigDecimal.valueOf(Objects.requireNonNullElse(event.getQuantity(), 0))).longValue();
|
||||
private BigDecimal resolveGiftUnitPrice(GameLuckyGiftBusinessEvent event, GiftConfigDTO giftConfig) {
|
||||
return Objects.nonNull(event.getGiftPrice()) ? event.getGiftPrice() : giftConfig.getGiftCandy();
|
||||
}
|
||||
|
||||
private long resolvePayAmount(GameLuckyGiftBusinessEvent event, BigDecimal giftUnitPrice) {
|
||||
if (giftUnitPrice == null) {
|
||||
return 0L;
|
||||
}
|
||||
return giftUnitPrice.multiply(BigDecimal.valueOf(Objects.requireNonNullElse(event.getQuantity(), 0))).longValue();
|
||||
}
|
||||
|
||||
private void sendLuckyGiftMessage(
|
||||
|
||||
@ -139,23 +139,24 @@ public class RoomVoiceProfileCommon {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private RoomVoiceProfileCO mergeActiveVoiceRoom(UserProfileDTO userProfile,
|
||||
RoomProfileManager manager,
|
||||
ActiveVoiceRoom activeVoiceRoom) {
|
||||
private RoomVoiceProfileCO mergeActiveVoiceRoom(UserProfileDTO userProfile,
|
||||
RoomProfileManager manager,
|
||||
ActiveVoiceRoom activeVoiceRoom) {
|
||||
|
||||
if (Objects.isNull(userProfile) || Objects.isNull(manager) || Objects.isNull(activeVoiceRoom)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
RoomVoiceProfileCO roomVoiceProfile = mergeRoomVoiceProfile(userProfile, manager);
|
||||
if (Objects.isNull(roomVoiceProfile)) {
|
||||
return null;
|
||||
}
|
||||
roomVoiceProfile.setHotRoom(activeVoiceRoom.getHot());
|
||||
roomVoiceProfile.setRoomGameIcon("");
|
||||
roomVoiceProfile.setUserSVipLevel(SVIPLevelEnum.valueOf(activeVoiceRoom.getSuperVipLevel()));
|
||||
return roomVoiceProfile;
|
||||
}
|
||||
RoomVoiceProfileCO roomVoiceProfile = mergeRoomVoiceProfile(userProfile, manager);
|
||||
if (Objects.isNull(roomVoiceProfile)) {
|
||||
return null;
|
||||
}
|
||||
roomVoiceProfile.putRoomMemberQuantity(toRoomMemberQuantity(activeVoiceRoom.getOnlineQuantity()));
|
||||
roomVoiceProfile.setHotRoom(activeVoiceRoom.getHot());
|
||||
roomVoiceProfile.setRoomGameIcon("");
|
||||
roomVoiceProfile.setUserSVipLevel(SVIPLevelEnum.valueOf(activeVoiceRoom.getSuperVipLevel()));
|
||||
return roomVoiceProfile;
|
||||
}
|
||||
|
||||
private RoomVoiceProfileCO mergeRoomVoiceProfile(UserProfileDTO userProfile,
|
||||
RoomProfileManager manager) {
|
||||
@ -185,5 +186,12 @@ public class RoomVoiceProfileCommon {
|
||||
&& !Objects.equals(manager.getEvent(), RoomEventEnum.CLOSE.name());
|
||||
}
|
||||
|
||||
private Integer toRoomMemberQuantity(Long onlineQuantity) {
|
||||
if (Objects.isNull(onlineQuantity) || onlineQuantity < 0) {
|
||||
return 0;
|
||||
}
|
||||
return onlineQuantity > Integer.MAX_VALUE ? Integer.MAX_VALUE : onlineQuantity.intValue();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,18 +1,30 @@
|
||||
package com.red.circle.other.app.convertor.sys;
|
||||
|
||||
import com.red.circle.framework.core.convertor.ConvertorModel;
|
||||
import com.red.circle.other.app.dto.clientobject.sys.CountryCodeCO;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode;
|
||||
import java.util.List;
|
||||
import org.mapstruct.Mapper;
|
||||
package com.red.circle.other.app.convertor.sys;
|
||||
|
||||
import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
|
||||
import com.red.circle.framework.core.convertor.ConvertorModel;
|
||||
import com.red.circle.other.app.dto.clientobject.sys.CountryCodeCO;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode;
|
||||
import java.util.List;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
/**
|
||||
* @author pengliang on 2021/3/10
|
||||
*/
|
||||
@Mapper(componentModel = ConvertorModel.SPRING)
|
||||
public interface SysCountryAppConvertor {
|
||||
|
||||
List<CountryCodeCO> toListCountryCodeCO(List<SysCountryCode> countryCodes);
|
||||
|
||||
CountryCodeCO toCountryCodeCO(SysCountryCode countryCode);
|
||||
}
|
||||
public interface SysCountryAppConvertor {
|
||||
|
||||
List<CountryCodeCO> toListCountryCodeCO(List<SysCountryCode> countryCodes);
|
||||
|
||||
@Mapping(target = "countryCodeAliases", source = ".")
|
||||
CountryCodeCO toCountryCodeCO(SysCountryCode countryCode);
|
||||
|
||||
default List<String> mapCountryCodeAliases(SysCountryCode countryCode) {
|
||||
if (countryCode == null) {
|
||||
return List.of();
|
||||
}
|
||||
return CountryCodeAliasUtils.normalizeCodes(
|
||||
CountryCodeAliasUtils.buildMatchCodes(countryCode.getAlphaTwo(), countryCode.getAlphaThree(),
|
||||
CountryCodeAliasUtils.parseAliasCodes(countryCode.getAliasCodes())));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,75 +0,0 @@
|
||||
// 路径: rc-service-other/other-application/src/main/java/com/red/circle/other/app/scheduler/EmptyRoomCleanTask.java
|
||||
package com.red.circle.other.app.scheduler;
|
||||
|
||||
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.component.redis.annotation.TaskCacheLock;
|
||||
import com.red.circle.live.inner.endpoint.LiveMicClient;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom;
|
||||
import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 清理空房间定时任务
|
||||
* 每2分钟清理一次DB中没人的房间
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(name = "scheduler.room-empty-clean", havingValue = "true", matchIfMissing = true)
|
||||
public class EmptyRoomCleanTask {
|
||||
|
||||
private final ActiveVoiceRoomService activeVoiceRoomService;
|
||||
private final LiveMicClient liveMicClient;
|
||||
|
||||
/**
|
||||
* 每2分钟清理一次空房间
|
||||
*/
|
||||
@Scheduled(cron = "0 */2 * * * ?")
|
||||
@TaskCacheLock(key = "EMPTY_ROOM_CLEAN_TASK", expireSecond = 59 * 2)
|
||||
public void cleanEmptyRooms() {
|
||||
try {
|
||||
// 获取所有活跃房间
|
||||
List<ActiveVoiceRoom> allRooms = activeVoiceRoomService.listDiscover(SysOriginPlatformEnum.LIKEI.name(),true,"",null,200);
|
||||
if (CollectionUtils.isEmpty(allRooms)) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Long> emptyRoomIds = new ArrayList<>();
|
||||
|
||||
// 检查每个房间的在线人数
|
||||
for (ActiveVoiceRoom room : allRooms) {
|
||||
// 跳过固定权重的房间(这些是固定展示的房间)
|
||||
if (room.getFixedWeights() != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Long roomUserCount = liveMicClient.getLiveRoomUserSize(room.getId()).getBody();
|
||||
if (roomUserCount != null && roomUserCount == 0) {
|
||||
emptyRoomIds.add(room.getId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 批量删除空房间
|
||||
if (!CollectionUtils.isEmpty(emptyRoomIds)) {
|
||||
activeVoiceRoomService.removeByIds(emptyRoomIds);
|
||||
log.info("清理空房间完成,删除房间数量: {}, 房间ID: {}", emptyRoomIds.size(), emptyRoomIds);
|
||||
} else {
|
||||
log.warn("清理空房间失败, 无法获取房间在线人数");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("清理空房间任务执行失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,92 @@
|
||||
package com.red.circle.other.app.scheduler;
|
||||
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.component.redis.annotation.TaskCacheLock;
|
||||
import com.red.circle.live.inner.endpoint.LiveMicClient;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom;
|
||||
import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService;
|
||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 定时对账在线房间人数,修正 ActiveVoiceRoom.onlineQuantity 漂移。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@ConditionalOnProperty(name = "scheduler.room-online-quantity-reconcile", havingValue = "true", matchIfMissing = true)
|
||||
public class RoomOnlineQuantityReconcileTask {
|
||||
|
||||
private static final int PER_SYS_ORIGIN_LIMIT = 200;
|
||||
|
||||
private final ActiveVoiceRoomService activeVoiceRoomService;
|
||||
private final LiveMicClient liveMicClient;
|
||||
|
||||
@Scheduled(cron = "0 */2 * * * ?")
|
||||
@TaskCacheLock(key = "ROOM_ONLINE_QUANTITY_RECONCILE_TASK", expireSecond = 59 * 2)
|
||||
public void reconcileOnlineQuantity() {
|
||||
try {
|
||||
List<ActiveVoiceRoom> activeRooms = listActiveRooms();
|
||||
if (CollectionUtils.isEmpty(activeRooms)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int correctedCount = 0;
|
||||
int failedCount = 0;
|
||||
for (ActiveVoiceRoom room : activeRooms) {
|
||||
if (Objects.isNull(room.getId()) || Objects.isNull(room.getRoomAccount())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Long actualQuantity = liveMicClient.getLiveRoomUserSize(room.getId()).getBody();
|
||||
actualQuantity = Objects.nonNull(actualQuantity) ? actualQuantity : 0L;
|
||||
Long currentQuantity = Objects.nonNull(room.getOnlineQuantity()) ? room.getOnlineQuantity() : 0L;
|
||||
if (Objects.equals(currentQuantity, actualQuantity)) {
|
||||
continue;
|
||||
}
|
||||
activeVoiceRoomService.updateQuantityByRoomAccount(room.getRoomAccount(), actualQuantity);
|
||||
correctedCount++;
|
||||
log.info("reconcile room online quantity, roomId={}, roomAccount={}, currentQuantity={}, actualQuantity={}",
|
||||
room.getId(), room.getRoomAccount(), currentQuantity, actualQuantity);
|
||||
} catch (Exception e) {
|
||||
failedCount++;
|
||||
log.warn("reconcile room online quantity failed, roomId={}, roomAccount={}",
|
||||
room.getId(), room.getRoomAccount(), e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("room online quantity reconcile finished, scanCount={}, correctedCount={}, failedCount={}",
|
||||
activeRooms.size(), correctedCount, failedCount);
|
||||
} catch (Exception e) {
|
||||
log.error("room online quantity reconcile task failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ActiveVoiceRoom> listActiveRooms() {
|
||||
Map<Long, ActiveVoiceRoom> rooms = new LinkedHashMap<>();
|
||||
for (SysOriginPlatformEnum sysOrigin : SysOriginPlatformEnum.getVoiceSystems()) {
|
||||
List<ActiveVoiceRoom> currentRooms = activeVoiceRoomService.listDiscover(
|
||||
sysOrigin.name(),
|
||||
true,
|
||||
"",
|
||||
null,
|
||||
PER_SYS_ORIGIN_LIMIT
|
||||
);
|
||||
if (CollectionUtils.isEmpty(currentRooms)) {
|
||||
continue;
|
||||
}
|
||||
currentRooms.forEach(room -> rooms.putIfAbsent(room.getId(), room));
|
||||
}
|
||||
return List.copyOf(rooms.values());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.red.circle.other.app.command.party3rd.callback.trtc;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.red.circle.external.inner.model.callback.trtc.EventInfo;
|
||||
import com.red.circle.external.inner.model.callback.trtc.TrtcCallbackEvent;
|
||||
import com.red.circle.other.app.common.live.OnlineRoomCommon;
|
||||
import com.red.circle.other.infra.database.cache.service.other.RoomManagerCacheService;
|
||||
import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class EnterRoomCallbackStrategyTest {
|
||||
|
||||
@Test
|
||||
void doOperation_shouldUpdateOnlineQuantityWithIncrementedRoomUserSize() {
|
||||
OnlineRoomCommon onlineRoomCommon = mock(OnlineRoomCommon.class);
|
||||
ActiveVoiceRoomService activeVoiceRoomService = mock(ActiveVoiceRoomService.class);
|
||||
RoomManagerCacheService roomManagerCacheService = mock(RoomManagerCacheService.class);
|
||||
EnterRoomCallbackStrategy strategy = new EnterRoomCallbackStrategy(
|
||||
onlineRoomCommon,
|
||||
activeVoiceRoomService,
|
||||
roomManagerCacheService
|
||||
);
|
||||
|
||||
TrtcCallbackEvent event = new TrtcCallbackEvent();
|
||||
EventInfo eventInfo = new EventInfo();
|
||||
eventInfo.setRoomId("123456");
|
||||
eventInfo.setUserId("9527");
|
||||
eventInfo.setEventTs("1710000000");
|
||||
event.setEventInfo(eventInfo);
|
||||
|
||||
when(activeVoiceRoomService.existsByRoomAccount("123456")).thenReturn(true);
|
||||
when(roomManagerCacheService.incrementNumberPeople("123456")).thenReturn(6L);
|
||||
|
||||
strategy.doOperation(event);
|
||||
|
||||
verify(activeVoiceRoomService).updateQuantityByRoomAccount("123456", 6L);
|
||||
verify(onlineRoomCommon, never()).addOnlineRoomByAccount("123456");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
package com.red.circle.other.app.common.gift;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.red.circle.component.redis.service.RedisService;
|
||||
import com.red.circle.external.inner.endpoint.message.ImGroupClient;
|
||||
import com.red.circle.external.inner.model.cmd.message.BroadcastGroupMsgBodyCmd;
|
||||
import com.red.circle.mq.business.model.event.gift.GameLuckyGiftBusinessEvent;
|
||||
import com.red.circle.mq.business.model.event.gift.GameLuckyGiftUser;
|
||||
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
|
||||
import com.red.circle.other.app.dto.clientobject.game.GameLuckyGiftMsgCO;
|
||||
import com.red.circle.other.app.service.task.RoomDailyTaskProgressService;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.infra.database.cache.service.other.GiftCacheService;
|
||||
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
|
||||
import com.red.circle.other.infra.database.rds.entity.game.GameLuckyGiftCount;
|
||||
import com.red.circle.other.infra.database.rds.service.game.GameLuckyGiftCountService;
|
||||
import com.red.circle.other.infra.database.rds.service.live.RoomMemberService;
|
||||
import com.red.circle.other.inner.model.dto.material.GiftConfigDTO;
|
||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
class LuckyGiftResultProcessorTest {
|
||||
|
||||
@Test
|
||||
void process_shouldUseGiftUnitPriceToCalculateMultiple() {
|
||||
GameLuckyGiftCountService gameLuckyGiftCountService = mock(GameLuckyGiftCountService.class);
|
||||
GiftCacheService giftCacheService = mock(GiftCacheService.class);
|
||||
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
||||
UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class);
|
||||
ImGroupClient imGroupClient = mock(ImGroupClient.class);
|
||||
RoomDailyTaskProgressService roomDailyTaskProgressService = mock(RoomDailyTaskProgressService.class);
|
||||
RoomMemberService roomMemberService = mock(RoomMemberService.class);
|
||||
RedisService redisService = mock(RedisService.class);
|
||||
RoomProfileManagerService roomProfileManagerService = mock(RoomProfileManagerService.class);
|
||||
GameLuckyGiftCommon gameLuckyGiftCommon = mock(GameLuckyGiftCommon.class);
|
||||
LuckyGiftResultProcessor processor = new LuckyGiftResultProcessor(
|
||||
gameLuckyGiftCountService,
|
||||
giftCacheService,
|
||||
userProfileGateway,
|
||||
userProfileAppConvertor,
|
||||
imGroupClient,
|
||||
roomDailyTaskProgressService,
|
||||
roomMemberService,
|
||||
redisService,
|
||||
roomProfileManagerService,
|
||||
gameLuckyGiftCommon
|
||||
);
|
||||
|
||||
GiftConfigDTO giftConfig = new GiftConfigDTO()
|
||||
.setId(11L)
|
||||
.setGiftCandy(BigDecimal.valueOf(173))
|
||||
.setGiftPhoto("gift.png");
|
||||
UserProfile senderProfile = new UserProfile();
|
||||
senderProfile.setId(1001L);
|
||||
senderProfile.setAccount("sender001");
|
||||
senderProfile.setUserNickname("sender");
|
||||
|
||||
UserProfile acceptProfile = new UserProfile();
|
||||
acceptProfile.setId(2002L);
|
||||
acceptProfile.setUserNickname("receiver");
|
||||
|
||||
UserProfileDTO senderProfileDTO = new UserProfileDTO();
|
||||
senderProfileDTO.setId(1001L);
|
||||
senderProfileDTO.setAccount("sender001");
|
||||
senderProfileDTO.setUserNickname("sender");
|
||||
senderProfileDTO.setUserAvatar("sender.png");
|
||||
|
||||
when(giftCacheService.getById(11L)).thenReturn(giftConfig);
|
||||
when(userProfileGateway.getByUserId(1001L)).thenReturn(senderProfile);
|
||||
when(userProfileGateway.getByUserId(2002L)).thenReturn(acceptProfile);
|
||||
when(userProfileAppConvertor.toUserProfileDTO(senderProfile)).thenReturn(senderProfileDTO);
|
||||
when(gameLuckyGiftCommon.getRewardMultipleType(20)).thenReturn("SUPER");
|
||||
when(roomMemberService.getRoomMember(3003L, 1001L)).thenReturn(null);
|
||||
|
||||
GameLuckyGiftBusinessEvent event = new GameLuckyGiftBusinessEvent()
|
||||
.setBusinessId("biz-001")
|
||||
.setUserId(1001L)
|
||||
.setRoomId(3003L)
|
||||
.setRoomAccount("room-account")
|
||||
.setSysOrigin("LIKEI")
|
||||
.setGiftId(11L)
|
||||
.setGiftPrice(BigDecimal.valueOf(173))
|
||||
.setQuantity(4)
|
||||
.setGiftCombos(0)
|
||||
.setRegionCode("SA")
|
||||
.setUsers(List.of(
|
||||
new GameLuckyGiftUser()
|
||||
.setId(90001L)
|
||||
.setAcceptUserId(2002L)
|
||||
));
|
||||
|
||||
LuckyGiftGoClient.LuckyGiftGoDrawResponse response = new LuckyGiftGoClient.LuckyGiftGoDrawResponse()
|
||||
.setBusinessId("biz-001")
|
||||
.setBalanceAfter(999999L)
|
||||
.setResults(List.of(
|
||||
new LuckyGiftGoClient.LuckyGiftGoDrawResult()
|
||||
.setId("90001")
|
||||
.setAcceptUserId(2002L)
|
||||
.setIsWin(true)
|
||||
.setRewardNum(3460L)
|
||||
));
|
||||
|
||||
processor.process(event, response);
|
||||
|
||||
ArgumentCaptor<GameLuckyGiftCount> countCaptor = ArgumentCaptor.forClass(GameLuckyGiftCount.class);
|
||||
verify(gameLuckyGiftCountService).saveOrUpdate(countCaptor.capture());
|
||||
GameLuckyGiftCount saved = countCaptor.getValue();
|
||||
assertEquals(Long.valueOf(692L), saved.getPayAmount());
|
||||
assertEquals(Integer.valueOf(20), saved.getMultiple());
|
||||
assertEquals(Long.valueOf(3460L), saved.getAwardAmount());
|
||||
|
||||
ArgumentCaptor<BroadcastGroupMsgBodyCmd> messageCaptor = ArgumentCaptor.forClass(BroadcastGroupMsgBodyCmd.class);
|
||||
verify(imGroupClient).sendMessageBroadcast(messageCaptor.capture());
|
||||
GameLuckyGiftMsgCO message = (GameLuckyGiftMsgCO) messageCaptor.getValue().getData();
|
||||
assertEquals(Integer.valueOf(20), message.getMultiple());
|
||||
assertEquals(Long.valueOf(3460L), message.getAwardAmount());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package com.red.circle.other.app.common.room;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.red.circle.other.app.convertor.live.RoomProfileAppConvertor;
|
||||
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
|
||||
import com.red.circle.other.app.dto.clientobject.family.RoomSettingCO;
|
||||
import com.red.circle.other.app.dto.clientobject.room.RoomVoiceProfileCO;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomCounter;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfileManager;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomSetting;
|
||||
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
|
||||
import com.red.circle.other.inner.enums.room.RoomEventEnum;
|
||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class RoomVoiceProfileCommonTest {
|
||||
|
||||
@Test
|
||||
void toListRoomVoiceProfileCO_shouldUseActiveVoiceRoomOnlineQuantityAsMemberQuantity() {
|
||||
UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
|
||||
UserProfileAppConvertor userProfileAppConvertor = mock(UserProfileAppConvertor.class);
|
||||
RoomProfileAppConvertor roomProfileAppConvertor = mock(RoomProfileAppConvertor.class);
|
||||
RoomProfileManagerService roomProfileManagerService = mock(RoomProfileManagerService.class);
|
||||
RoomVoiceProfileCommon roomVoiceProfileCommon = new RoomVoiceProfileCommon(
|
||||
userProfileGateway,
|
||||
userProfileAppConvertor,
|
||||
roomProfileAppConvertor,
|
||||
roomProfileManagerService
|
||||
);
|
||||
|
||||
ActiveVoiceRoom activeVoiceRoom = new ActiveVoiceRoom()
|
||||
.setId(10001L)
|
||||
.setUserId(20001L)
|
||||
.setOnlineQuantity(6L)
|
||||
.setSuperVipLevel("NONE");
|
||||
|
||||
RoomProfileManager roomProfileManager = new RoomProfileManager();
|
||||
roomProfileManager.setId(10001L);
|
||||
roomProfileManager.setUserId(20001L);
|
||||
roomProfileManager.setDel(Boolean.FALSE);
|
||||
roomProfileManager.setEvent(RoomEventEnum.AVAILABLE.name());
|
||||
roomProfileManager.setSetting(RoomSetting.createDefaultRoomSetting());
|
||||
roomProfileManager.setCounter(new RoomCounter().setMemberCount(1).setAdminCount(0));
|
||||
|
||||
UserProfileDTO userProfileDTO = new UserProfileDTO();
|
||||
userProfileDTO.setId(20001L);
|
||||
|
||||
RoomVoiceProfileCO convertedProfile = new RoomVoiceProfileCO()
|
||||
.setId(10001L)
|
||||
.setUserId(20001L);
|
||||
|
||||
when(roomProfileManagerService.mapByRoomIds(java.util.Set.of(10001L)))
|
||||
.thenReturn(Map.of(10001L, roomProfileManager));
|
||||
when(userProfileGateway.mapByUserIds(java.util.Set.of(20001L)))
|
||||
.thenReturn(Map.of());
|
||||
when(userProfileAppConvertor.toMapUserProfileDTO(anyMap()))
|
||||
.thenReturn(Map.of(20001L, userProfileDTO));
|
||||
when(roomProfileAppConvertor.toRoomVoiceProfileCO(roomProfileManager))
|
||||
.thenReturn(convertedProfile);
|
||||
when(roomProfileAppConvertor.toRoomSettingCO(roomProfileManager.getSetting()))
|
||||
.thenReturn(new RoomSettingCO());
|
||||
|
||||
List<RoomVoiceProfileCO> roomProfiles = roomVoiceProfileCommon.toListRoomVoiceProfileCO(
|
||||
List.of(activeVoiceRoom));
|
||||
|
||||
assertEquals(1, roomProfiles.size());
|
||||
assertEquals("6", getExtValue(roomProfiles.get(0), "memberQuantity"));
|
||||
}
|
||||
|
||||
private Object getExtValue(RoomVoiceProfileCO roomVoiceProfileCO, String key) {
|
||||
Map<?, ?> extValues = findExtValues(roomVoiceProfileCO);
|
||||
assertNotNull(extValues, "extValues should exist on RoomVoiceProfileCO");
|
||||
return extValues.get(key);
|
||||
}
|
||||
|
||||
private Map<?, ?> findExtValues(Object target) {
|
||||
Class<?> current = target.getClass();
|
||||
while (current != null) {
|
||||
try {
|
||||
Field field = current.getDeclaredField("extValues");
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(target);
|
||||
if (value instanceof Map<?, ?> extValues) {
|
||||
return extValues;
|
||||
}
|
||||
return null;
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
current = current.getSuperclass();
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException("read extValues failed", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
package com.red.circle.other.app.dto.clientobject.sys;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.red.circle.framework.dto.ClientObject;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.red.circle.framework.dto.ClientObject;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@ -40,10 +41,15 @@ public class CountryCodeCO extends ClientObject {
|
||||
*/
|
||||
private String countryName;
|
||||
|
||||
/**
|
||||
* 别名.
|
||||
*/
|
||||
private String aliasName;
|
||||
/**
|
||||
* 别名.
|
||||
*/
|
||||
private String aliasName;
|
||||
|
||||
/**
|
||||
* 国家码别名集合.
|
||||
*/
|
||||
private List<String> countryCodeAliases;
|
||||
|
||||
/**
|
||||
* 国旗.
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
package com.red.circle.other.infra.common.sys;
|
||||
|
||||
import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.SysCountryCodeService;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 国家码别名支持.
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CountryCodeAliasSupport {
|
||||
|
||||
private final SysCountryCodeService sysCountryCodeService;
|
||||
|
||||
/**
|
||||
* 获取某个国家码的全部可匹配代码.
|
||||
*/
|
||||
public Set<String> getMatchCodes(String code) {
|
||||
String normalized = CountryCodeAliasUtils.normalize(code);
|
||||
if (StringUtils.isBlank(normalized)) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
SysCountryCode sysCountryCode = sysCountryCodeService.getByCode(normalized);
|
||||
if (sysCountryCode == null) {
|
||||
return CountryCodeAliasUtils.legacyAliases(normalized);
|
||||
}
|
||||
|
||||
return CountryCodeAliasUtils.buildMatchCodes(sysCountryCode.getAlphaTwo(),
|
||||
sysCountryCode.getAlphaThree(),
|
||||
CountryCodeAliasUtils.parseAliasCodes(sysCountryCode.getAliasCodes()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 扩展多组国家码.
|
||||
*/
|
||||
public Set<String> expandCodes(Collection<String> codes) {
|
||||
if (codes == null || codes.isEmpty()) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
LinkedHashSet<String> result = new LinkedHashSet<>();
|
||||
for (String code : codes) {
|
||||
result.addAll(getMatchCodes(code));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 两个国家码是否匹配.
|
||||
*/
|
||||
public boolean matches(String leftCode, String rightCode) {
|
||||
Set<String> leftCodes = getMatchCodes(leftCode);
|
||||
Set<String> rightCodes = getMatchCodes(rightCode);
|
||||
if (leftCodes.isEmpty() || rightCodes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return leftCodes.stream().anyMatch(rightCodes::contains);
|
||||
}
|
||||
|
||||
/**
|
||||
* 逗号分隔国家列表是否包含指定国家码.
|
||||
*/
|
||||
public boolean containsCode(String csvCodes, String countryCode) {
|
||||
if (StringUtils.isBlank(csvCodes) || StringUtils.isBlank(countryCode)) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.stream(csvCodes.split(","))
|
||||
.map(CountryCodeAliasUtils::normalize)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.anyMatch(code -> matches(code, countryCode));
|
||||
}
|
||||
}
|
||||
@ -1,26 +1,43 @@
|
||||
package com.red.circle.other.infra.convertor.sys;
|
||||
|
||||
import com.red.circle.framework.core.convertor.ConvertorModel;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode;
|
||||
import com.red.circle.other.inner.model.cmd.sys.SysCountryCodeCmd;
|
||||
import com.red.circle.other.inner.model.dto.sys.SysCountryCodeDTO;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.mapstruct.Mapper;
|
||||
package com.red.circle.other.infra.convertor.sys;
|
||||
|
||||
import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
|
||||
import com.red.circle.framework.core.convertor.ConvertorModel;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode;
|
||||
import com.red.circle.other.inner.model.cmd.sys.SysCountryCodeCmd;
|
||||
import com.red.circle.other.inner.model.dto.sys.SysCountryCodeDTO;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
/**
|
||||
* @author pengliang on 2023/5/24
|
||||
*/
|
||||
@Mapper(componentModel = ConvertorModel.SPRING)
|
||||
public interface CountryCodeInnerConvertor {
|
||||
|
||||
SysCountryCodeDTO toSysCountryCodeDTO(SysCountryCode sysCountryCode);
|
||||
|
||||
List<SysCountryCodeDTO> toListSysCountryCodeDTO(List<SysCountryCode> sysCountryCodes);
|
||||
|
||||
Map<Long, SysCountryCodeDTO> toMapLongSysCountryCodeDTO(
|
||||
Map<Long, SysCountryCode> sysCountryCodeMap);
|
||||
|
||||
SysCountryCode toSysCountryCode(SysCountryCodeCmd cmd);
|
||||
|
||||
}
|
||||
public interface CountryCodeInnerConvertor {
|
||||
|
||||
@Mapping(target = "countryCodeAliases", source = ".")
|
||||
SysCountryCodeDTO toSysCountryCodeDTO(SysCountryCode sysCountryCode);
|
||||
|
||||
List<SysCountryCodeDTO> toListSysCountryCodeDTO(List<SysCountryCode> sysCountryCodes);
|
||||
|
||||
Map<Long, SysCountryCodeDTO> toMapLongSysCountryCodeDTO(
|
||||
Map<Long, SysCountryCode> sysCountryCodeMap);
|
||||
|
||||
@Mapping(target = "aliasCodes", source = "countryCodeAliases")
|
||||
SysCountryCode toSysCountryCode(SysCountryCodeCmd cmd);
|
||||
|
||||
default List<String> mapCountryCodeAliases(SysCountryCode sysCountryCode) {
|
||||
if (sysCountryCode == null) {
|
||||
return List.of();
|
||||
}
|
||||
return CountryCodeAliasUtils.normalizeCodes(
|
||||
CountryCodeAliasUtils.buildMatchCodes(sysCountryCode.getAlphaTwo(), sysCountryCode.getAlphaThree(),
|
||||
CountryCodeAliasUtils.parseAliasCodes(sysCountryCode.getAliasCodes())));
|
||||
}
|
||||
|
||||
default String mapCountryCodeAliases(List<String> countryCodeAliases) {
|
||||
return CountryCodeAliasUtils.toAliasCodesJson(countryCodeAliases);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
package com.red.circle.other.infra.database.mongo.service.live.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.framework.mybatis.constant.PageConstant;
|
||||
import com.red.circle.other.infra.database.mongo.dto.query.live.ActiveVoiceRoomQuery;
|
||||
package com.red.circle.other.infra.database.mongo.service.live.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||
import com.red.circle.framework.mybatis.constant.PageConstant;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.mongo.dto.query.live.ActiveVoiceRoomQuery;
|
||||
import com.red.circle.other.infra.database.mongo.dto.query.live.FamilyOnlineRoomQuery;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.ActiveVoiceRoom;
|
||||
import com.red.circle.other.infra.database.mongo.service.live.ActiveVoiceRoomService;
|
||||
@ -32,12 +33,13 @@ import org.springframework.stereotype.Service;
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
private static final Set<String> TR_REGIONS = Set.of("TR");
|
||||
private static final Set<String> SA_REGIONS = Set.of("BD","SA", "IN", "PK");
|
||||
public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
private static final Set<String> TR_REGIONS = Set.of("TR");
|
||||
private static final Set<String> SA_REGIONS = Set.of("BD","SA", "IN", "PK");
|
||||
private static final Set<String> AR_REGIONS = Set.of("AE", "AR", "BH", "DJ", "DZ", "EG", "EY", "ER", "IL", "IQ", "JO", "KM", "KW", "LB", "LY", "MA", "MR", "OM", "PS", "QA", "SD", "SO", "SS", "SY", "TD", "TN", "YE");
|
||||
private static final Set<String> OTHER_REGIONS = Set.of("OTHER", "PH", "ID", "GH", "IR", "AF", "NG", "DE", "MYS", "TM", "AZ", "NP");
|
||||
private static final Set<String> ALL_SPECIAL_REGIONS;
|
||||
@ -116,9 +118,9 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
criteria.and("roomAccount").is(qryCmd.getRoomAccount());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(qryCmd.getCountryCode())) {
|
||||
criteria.and("countryCode").is(qryCmd.getCountryCode());
|
||||
}
|
||||
if (StringUtils.isNotBlank(qryCmd.getCountryCode())) {
|
||||
criteria.and("countryCode").in(countryCodeAliasSupport.getMatchCodes(qryCmd.getCountryCode()));
|
||||
}
|
||||
|
||||
Query query = Query.query(criteria);
|
||||
|
||||
@ -148,10 +150,10 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
if (userRegionGroup == null && !isAllRegion) {
|
||||
criteria.and("region").nin(excludeRegions);
|
||||
}
|
||||
// SA_REGIONS 用户只能看到相同国家的房间
|
||||
if (SA_REGIONS.contains(region) && !isAllRegion && StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").is(countryCode);
|
||||
}
|
||||
// SA_REGIONS 用户只能看到相同国家的房间
|
||||
if (SA_REGIONS.contains(region) && !isAllRegion && StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").in(countryCodeAliasSupport.getMatchCodes(countryCode));
|
||||
}
|
||||
Aggregation aggregation = Aggregation.newAggregation(
|
||||
// 1. 匹配国家(可选条件)
|
||||
Aggregation.match(criteria),
|
||||
@ -237,9 +239,10 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
public List<ActiveVoiceRoom> listSearchCountryRoom(String sysOrigin, String countryCode,
|
||||
Integer limit) {
|
||||
|
||||
Query query = Query.query(
|
||||
Criteria.where("sysOrigin").is(sysOrigin).and("countryCode").is(countryCode)
|
||||
);
|
||||
Query query = Query.query(
|
||||
Criteria.where("sysOrigin").is(sysOrigin)
|
||||
.and("countryCode").in(countryCodeAliasSupport.getMatchCodes(countryCode))
|
||||
);
|
||||
|
||||
return mongoTemplate.find(query.limit(limit), ActiveVoiceRoom.class);
|
||||
}
|
||||
@ -258,12 +261,12 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActiveVoiceRoom> listExcludeCountry(AppActiveVoiceRoomQryCmd query) {
|
||||
Criteria criteria = Criteria.where("sysOrigin").is(query.getSysOrigin());
|
||||
if (StringUtils.isNotBlank(query.getCountryCode())) {
|
||||
criteria.and("countryCode").nin(query.getCountryCode());
|
||||
criteria.and("region").nin("AR", "TR");
|
||||
}
|
||||
public List<ActiveVoiceRoom> listExcludeCountry(AppActiveVoiceRoomQryCmd query) {
|
||||
Criteria criteria = Criteria.where("sysOrigin").is(query.getSysOrigin());
|
||||
if (StringUtils.isNotBlank(query.getCountryCode())) {
|
||||
criteria.and("countryCode").nin(countryCodeAliasSupport.getMatchCodes(query.getCountryCode()));
|
||||
criteria.and("region").nin("AR", "TR");
|
||||
}
|
||||
Query mQuery = Query.query(criteria);
|
||||
mQuery.with(Sort.by(Sort.Order.desc("onlineQuantity")));
|
||||
return mongoTemplate.find(mQuery.limit(query.getLimit()), ActiveVoiceRoom.class);
|
||||
@ -278,9 +281,9 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
criteria.and("id").is(query.getRoomId());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(query.getCountryCode())) {
|
||||
criteria.and("countryCode").is(query.getCountryCode());
|
||||
}
|
||||
if (StringUtils.isNotBlank(query.getCountryCode())) {
|
||||
criteria.and("countryCode").in(countryCodeAliasSupport.getMatchCodes(query.getCountryCode()));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(query.getRoomTag())) {
|
||||
criteria.and("roomTag").is(query.getRoomTag());
|
||||
@ -318,7 +321,8 @@ public class ActiveVoiceRoomServiceImpl implements ActiveVoiceRoomService {
|
||||
if (Objects.nonNull(query.getRoomId())) {
|
||||
criteria.and("roomId").is(query.getRoomId());
|
||||
}
|
||||
criteria.and("countryCode").nin("SA", "AE", "EG", "MA", "US");
|
||||
criteria.and("countryCode").nin(
|
||||
countryCodeAliasSupport.expandCodes(List.of("SA", "AE", "EG", "MA", "US")));
|
||||
|
||||
if (StringUtils.isNotBlank(query.getRoomTag())) {
|
||||
criteria.and("roomTag").is(query.getRoomTag());
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
package com.red.circle.other.infra.database.mongo.service.live.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.red.circle.common.business.core.ReplaceString;
|
||||
import com.red.circle.common.business.core.SensitiveWordFilter;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.red.circle.common.business.core.ReplaceString;
|
||||
import com.red.circle.common.business.core.SensitiveWordFilter;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.cache.service.other.RoomManagerCacheService;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomCounter;
|
||||
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile;
|
||||
@ -57,6 +58,7 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
|
||||
private final RedisTemplate<String, String> redisTemplate;
|
||||
private final ActiveVoiceRoomService activeVoiceRoomService;
|
||||
private final RoomManagerCacheService roomManagerCacheService;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
/**
|
||||
* Redis缓存Key前缀
|
||||
@ -262,11 +264,11 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
|
||||
public List<RoomProfileManager> listSelectiveLimit100(String sysOrigin, String countryCode,
|
||||
List<Long> excludeIds) {
|
||||
|
||||
Criteria criteria = Criteria.where("sysOrigin").in(sysOrigin)
|
||||
.and("del").is(Boolean.FALSE);
|
||||
if (StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").is(countryCode);
|
||||
}
|
||||
Criteria criteria = Criteria.where("sysOrigin").in(sysOrigin)
|
||||
.and("del").is(Boolean.FALSE);
|
||||
if (StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").in(countryCodeAliasSupport.getMatchCodes(countryCode));
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(excludeIds)) {
|
||||
criteria.and("id").nin(excludeIds);
|
||||
@ -282,10 +284,10 @@ public class RoomProfileManagerServiceImpl implements RoomProfileManagerService
|
||||
public List<RoomProfileManager> listSelectiveLimit100(String sysOrigin,
|
||||
List<String> countryCodes, List<Long> excludeIds) {
|
||||
|
||||
Criteria criteria = Criteria.where("sysOrigin").in(sysOrigin);
|
||||
if (CollectionUtils.isNotEmpty(countryCodes)) {
|
||||
criteria.and("countryCode").nin(countryCodes);
|
||||
}
|
||||
Criteria criteria = Criteria.where("sysOrigin").in(sysOrigin);
|
||||
if (CollectionUtils.isNotEmpty(countryCodes)) {
|
||||
criteria.and("countryCode").nin(countryCodeAliasSupport.expandCodes(countryCodes));
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(excludeIds)) {
|
||||
criteria.and("id").nin(excludeIds);
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
package com.red.circle.other.infra.database.mongo.service.team.team.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.red.circle.other.infra.database.mongo.dto.team.TeamPolicy;
|
||||
package com.red.circle.other.infra.database.mongo.service.team.team.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.mongo.dto.team.TeamPolicy;
|
||||
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyManager;
|
||||
import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyManagerService;
|
||||
import com.red.circle.other.inner.enums.team.TeamPolicyTypeEnum;
|
||||
@ -25,9 +26,10 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TeamPolicyManagerServiceImpl implements TeamPolicyManagerService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
public class TeamPolicyManagerServiceImpl implements TeamPolicyManagerService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
@Override
|
||||
public List<TeamPolicyManager> listSysOriginRegion(String sysOrigin, String region) {
|
||||
@ -57,9 +59,9 @@ public class TeamPolicyManagerServiceImpl implements TeamPolicyManagerService {
|
||||
}else {
|
||||
criteria.and("policyType").ne(TeamPolicyTypeEnum.SALARY_DIAMOND.name());
|
||||
}
|
||||
if (StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").is(countryCode);
|
||||
}
|
||||
if (StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").in(countryCodeAliasSupport.getMatchCodes(countryCode));
|
||||
}
|
||||
|
||||
return mongoTemplate.find( Query.query(criteria).with(Sort.by(Sort.Order.desc("createTime"))), TeamPolicyManager.class);
|
||||
}
|
||||
@ -96,9 +98,9 @@ public class TeamPolicyManagerServiceImpl implements TeamPolicyManagerService {
|
||||
}else {
|
||||
criteria.and("policyType").ne(TeamPolicyTypeEnum.SALARY_DIAMOND.name());
|
||||
}
|
||||
if (StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").is(countryCode);
|
||||
}
|
||||
if (StringUtils.isNotBlank(countryCode)) {
|
||||
criteria.and("countryCode").in(countryCodeAliasSupport.getMatchCodes(countryCode));
|
||||
}
|
||||
|
||||
return mongoTemplate.findOne(Query.query(criteria), TeamPolicyManager.class);
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package com.red.circle.other.infra.database.rds.entity.sys;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
package com.red.circle.other.infra.database.rds.entity.sys;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
@ -61,8 +61,14 @@ public class SysCountryCode extends TimestampBaseEntity {
|
||||
/**
|
||||
* 别名.
|
||||
*/
|
||||
@TableField("alias_name")
|
||||
private String aliasName;
|
||||
@TableField("alias_name")
|
||||
private String aliasName;
|
||||
|
||||
/**
|
||||
* 国家码别名集合(JSON数组).
|
||||
*/
|
||||
@TableField("alias_codes")
|
||||
private String aliasCodes;
|
||||
|
||||
/**
|
||||
* 代码分配情况.
|
||||
|
||||
@ -1,20 +1,24 @@
|
||||
package com.red.circle.other.infra.database.rds.service.sys.impl;
|
||||
|
||||
import com.red.circle.framework.dto.PageResult;
|
||||
import com.red.circle.framework.mybatis.constant.PageConstant;
|
||||
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||
import com.red.circle.other.infra.database.rds.dao.sys.BannerConfigDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.BannerConfig;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.BannerConfigService;
|
||||
package com.red.circle.other.infra.database.rds.service.sys.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.red.circle.framework.dto.PageResult;
|
||||
import com.red.circle.framework.mybatis.constant.PageConstant;
|
||||
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.database.rds.dao.sys.BannerConfigDAO;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.BannerConfig;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.BannerConfigService;
|
||||
import com.red.circle.other.inner.model.cmd.sys.SysBannerConfigQryCmd;
|
||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.text.StringUtils;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -24,9 +28,12 @@ import org.springframework.stereotype.Service;
|
||||
* @author pengliang
|
||||
* @since 2021-01-26
|
||||
*/
|
||||
@Service
|
||||
public class BannerConfigServiceImpl extends
|
||||
BaseServiceImpl<BannerConfigDAO, BannerConfig> implements BannerConfigService {
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BannerConfigServiceImpl extends
|
||||
BaseServiceImpl<BannerConfigDAO, BannerConfig> implements BannerConfigService {
|
||||
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
@Override
|
||||
public List<BannerConfig> listEffective(String sysOrigin, String platform, String countryCode, List<String> types) {
|
||||
@ -37,7 +44,7 @@ public class BannerConfigServiceImpl extends
|
||||
wrapper.in(BannerConfig::getPlatform, "", platform)
|
||||
)
|
||||
.and(StringUtils.isNotBlank(countryCode), wrapper ->
|
||||
wrapper.apply("(country_code = '' OR FIND_IN_SET({0}, country_code))", countryCode)
|
||||
applyCountryCodeFilter(wrapper, countryCode)
|
||||
)
|
||||
.gt(BannerConfig::getExpiredTime, LocalDateTime.now())
|
||||
.eq(BannerConfig::getShowcase, Boolean.TRUE)
|
||||
@ -52,9 +59,9 @@ public class BannerConfigServiceImpl extends
|
||||
.and(StringUtils.isNotBlank(query.getPlatform()), wrapper ->
|
||||
wrapper.in(BannerConfig::getPlatform, "", query.getPlatform())
|
||||
)
|
||||
.and(StringUtils.isNotBlank(query.getCountryCode()), wrapper ->
|
||||
wrapper.apply("(country_code = '' OR FIND_IN_SET({0}, country_code))", query.getCountryCode())
|
||||
)
|
||||
.and(StringUtils.isNotBlank(query.getCountryCode()), wrapper ->
|
||||
applyCountryCodeFilter(wrapper, query.getCountryCode())
|
||||
)
|
||||
.eq(Objects.equals(query.getShowcase(), 1), BannerConfig::getShowcase, Boolean.TRUE)
|
||||
.gt(Objects.equals(query.getShowcase(), 1), BannerConfig::getExpiredTime, TimestampUtils.now())
|
||||
.eq(Objects.equals(query.getShowcase(), 2), BannerConfig::getShowcase, Boolean.FALSE)
|
||||
@ -66,7 +73,7 @@ public class BannerConfigServiceImpl extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean updateInfo(BannerConfig bannerConfig) {
|
||||
public Boolean updateInfo(BannerConfig bannerConfig) {
|
||||
return update()
|
||||
.set(BannerConfig::getCover, bannerConfig.getCover())
|
||||
.set(BannerConfig::getSmallCover, bannerConfig.getSmallCover())
|
||||
@ -82,9 +89,22 @@ public class BannerConfigServiceImpl extends
|
||||
.set(BannerConfig::getStartTime, bannerConfig.getStartTime())
|
||||
.set(BannerConfig::getSort, bannerConfig.getSort())
|
||||
.set(BannerConfig::getRegions, bannerConfig.getRegions())
|
||||
.eq(BannerConfig::getId, bannerConfig.getId())
|
||||
.last(PageConstant.LIMIT_ONE)
|
||||
.execute();
|
||||
}
|
||||
|
||||
}
|
||||
.eq(BannerConfig::getId, bannerConfig.getId())
|
||||
.last(PageConstant.LIMIT_ONE)
|
||||
.execute();
|
||||
}
|
||||
|
||||
private void applyCountryCodeFilter(LambdaQueryWrapper<BannerConfig> wrapper, String countryCode) {
|
||||
Set<String> countryCodes = countryCodeAliasSupport.getMatchCodes(countryCode);
|
||||
List<String> aliasList = new ArrayList<>(countryCodes);
|
||||
StringBuilder sql = new StringBuilder("(country_code = ''");
|
||||
Object[] params = new Object[aliasList.size()];
|
||||
for (int i = 0; i < aliasList.size(); i++) {
|
||||
sql.append(" OR FIND_IN_SET({").append(i).append("}, country_code)");
|
||||
params[i] = aliasList.get(i);
|
||||
}
|
||||
sql.append(")");
|
||||
wrapper.apply(sql.toString(), params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
package com.red.circle.other.infra.database.rds.service.sys.impl;
|
||||
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||
package com.red.circle.other.infra.database.rds.service.sys.impl;
|
||||
|
||||
import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||
import com.red.circle.framework.dto.PageResult;
|
||||
import com.red.circle.framework.mybatis.constant.PageConstant;
|
||||
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
|
||||
@ -35,20 +36,39 @@ public class SysCountryCodeServiceImpl extends
|
||||
BaseServiceImpl<SysCountryCodeDAO, SysCountryCode> implements SysCountryCodeService {
|
||||
|
||||
@Override
|
||||
public SysCountryCode getByCode(String code) {
|
||||
if (StringUtils.isBlank(code)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int len = code.length();
|
||||
boolean isTwo = Objects.equals(len, NumConstant.TWO);
|
||||
String upperCaseCode = code.toUpperCase();
|
||||
return query()
|
||||
.eq(isTwo, SysCountryCode::getAlphaTwo, upperCaseCode)
|
||||
.eq(!isTwo, SysCountryCode::getAlphaThree, upperCaseCode)
|
||||
.last(PageConstant.LIMIT_ONE)
|
||||
.getOne();
|
||||
}
|
||||
public SysCountryCode getByCode(String code) {
|
||||
if (StringUtils.isBlank(code)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String normalizedCode = CountryCodeAliasUtils.normalize(code);
|
||||
SysCountryCode countryCode = getByExactCode(normalizedCode);
|
||||
if (Objects.nonNull(countryCode)) {
|
||||
return countryCode;
|
||||
}
|
||||
|
||||
return query().list().stream()
|
||||
.filter(item -> CountryCodeAliasUtils
|
||||
.buildMatchCodes(item.getAlphaTwo(), item.getAlphaThree(),
|
||||
CountryCodeAliasUtils.parseAliasCodes(item.getAliasCodes()))
|
||||
.contains(normalizedCode))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private SysCountryCode getByExactCode(String code) {
|
||||
if (StringUtils.isBlank(code)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int len = code.length();
|
||||
boolean isTwo = Objects.equals(len, NumConstant.TWO);
|
||||
return query()
|
||||
.eq(isTwo, SysCountryCode::getAlphaTwo, code)
|
||||
.eq(!isTwo, SysCountryCode::getAlphaThree, code)
|
||||
.last(PageConstant.LIMIT_ONE)
|
||||
.getOne();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SysCountryCode> listOpenCountry() {
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
package com.red.circle.other.infra.gateway.user;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.domain.model.user.ability.RegionConfig;
|
||||
package com.red.circle.other.infra.gateway.user;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
|
||||
import com.red.circle.other.domain.model.user.UserProfile;
|
||||
import com.red.circle.other.domain.model.user.ability.RegionConfig;
|
||||
import com.red.circle.other.infra.common.sys.CountryCodeAliasSupport;
|
||||
import com.red.circle.other.infra.convertor.user.UserRegionInfraConvertor;
|
||||
import com.red.circle.other.infra.database.cache.service.user.SysRegionCacheService;
|
||||
import com.red.circle.other.infra.database.cache.service.user.UserRegionCacheService;
|
||||
@ -51,9 +52,10 @@ public class UserRegionGatewayImpl implements UserRegionGateway {
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final SysRegionCacheService sysRegionCacheService;
|
||||
private final SysRegionConfigService sysRegionConfigService;
|
||||
private final UserRegionInfraConvertor userRegionInfraConvertor;
|
||||
private final SysRegionAssistConfigService sysRegionAssistConfigService;
|
||||
private final UserRegionCacheService userRegionCacheService;
|
||||
private final UserRegionInfraConvertor userRegionInfraConvertor;
|
||||
private final SysRegionAssistConfigService sysRegionAssistConfigService;
|
||||
private final UserRegionCacheService userRegionCacheService;
|
||||
private final CountryCodeAliasSupport countryCodeAliasSupport;
|
||||
|
||||
/**
|
||||
* key=用户id, value=区域code 获取一组区域code.
|
||||
@ -182,15 +184,15 @@ public class UserRegionGatewayImpl implements UserRegionGateway {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2.1 国家匹配
|
||||
if (StringUtils.isNotBlank(userProfile.getCountryCode())) {
|
||||
SysRegionConfig regionConfig = configs.stream()
|
||||
.filter(region -> StringUtils.containsIgnoreCase(region.getCountryCodes(),
|
||||
userProfile.getCountryCode())
|
||||
).findFirst().orElse(null);
|
||||
UserRegionDTO userRegion = createUserRegionDTO(userProfile, regionConfig);
|
||||
if (Objects.nonNull(userRegion)) {
|
||||
userRegions.add(userRegion);
|
||||
// 2.1 国家匹配
|
||||
if (StringUtils.isNotBlank(userProfile.getCountryCode())) {
|
||||
SysRegionConfig regionConfig = configs.stream()
|
||||
.filter(region -> countryCodeAliasSupport.containsCode(region.getCountryCodes(),
|
||||
userProfile.getCountryCode()))
|
||||
.findFirst().orElse(null);
|
||||
UserRegionDTO userRegion = createUserRegionDTO(userProfile, regionConfig);
|
||||
if (Objects.nonNull(userRegion)) {
|
||||
userRegions.add(userRegion);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -904,12 +906,12 @@ public class UserRegionGatewayImpl implements UserRegionGateway {
|
||||
|
||||
if (StringUtils.isNotBlank(userProfile.getCountryCode())) {
|
||||
|
||||
SysRegionConfig sysRegionConfig = configs.stream()
|
||||
.filter(region -> StringUtils.isNotBlank(region.getCountryCodes())
|
||||
&& StringUtils.isNotBlank(userProfile.getCountryCode())
|
||||
&& region.getCountryCodes().toLowerCase()
|
||||
.contains(userProfile.getCountryCode().toLowerCase())).findFirst()
|
||||
.orElse(null);
|
||||
SysRegionConfig sysRegionConfig = configs.stream()
|
||||
.filter(region -> StringUtils.isNotBlank(region.getCountryCodes())
|
||||
&& StringUtils.isNotBlank(userProfile.getCountryCode())
|
||||
&& countryCodeAliasSupport.containsCode(region.getCountryCodes(),
|
||||
userProfile.getCountryCode())).findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (Objects.nonNull(sysRegionConfig)) {
|
||||
resultMap.put(userProfile.getId(), sysRegionConfig);
|
||||
|
||||
64
sql/20260420_mifapay_order_mysql.sql
Normal file
64
sql/20260420_mifapay_order_mysql.sql
Normal file
@ -0,0 +1,64 @@
|
||||
SET @table_schema = DATABASE();
|
||||
|
||||
SET @ddl = IF(
|
||||
EXISTS(
|
||||
SELECT 1
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @table_schema
|
||||
AND TABLE_NAME = 'order_user_purchase_pay'
|
||||
AND COLUMN_NAME = 'receipt_type'
|
||||
),
|
||||
'SELECT 1',
|
||||
"ALTER TABLE `order_user_purchase_pay` ADD COLUMN `receipt_type` varchar(32) NOT NULL DEFAULT 'PAYMENT' COMMENT '单据类型 PAYMENT/RECEIPT' AFTER `reference_id`"
|
||||
);
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl = IF(
|
||||
EXISTS(
|
||||
SELECT 1
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @table_schema
|
||||
AND TABLE_NAME = 'order_user_purchase_pay'
|
||||
AND COLUMN_NAME = 'product_descriptor'
|
||||
),
|
||||
'SELECT 1',
|
||||
"ALTER TABLE `order_user_purchase_pay` ADD COLUMN `product_descriptor` varchar(255) NOT NULL DEFAULT '' COMMENT '商品描述' AFTER `product_content`"
|
||||
);
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @ddl = IF(
|
||||
EXISTS(
|
||||
SELECT 1
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @table_schema
|
||||
AND TABLE_NAME = 'order_user_purchase_pay'
|
||||
AND COLUMN_NAME = 'reason'
|
||||
),
|
||||
'SELECT 1',
|
||||
"ALTER TABLE `order_user_purchase_pay` ADD COLUMN `reason` varchar(255) NOT NULL DEFAULT '' COMMENT '失败或挂起原因' AFTER `pay_status`"
|
||||
);
|
||||
PREPARE stmt FROM @ddl;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
UPDATE `order_user_purchase_pay`
|
||||
SET `receipt_type` = 'PAYMENT'
|
||||
WHERE `receipt_type` = '';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `order_user_purchase_pay_notice` (
|
||||
`id` bigint NOT NULL COMMENT '主键ID',
|
||||
`purchase_pay_id` bigint NOT NULL COMMENT '支付预订单ID',
|
||||
`event_id` varchar(128) NOT NULL DEFAULT '' COMMENT '事件标识',
|
||||
`notice_type` varchar(64) NOT NULL DEFAULT '' COMMENT '通知类型',
|
||||
`notice_data` longtext COMMENT '通知内容(JSON)',
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`create_user` bigint DEFAULT NULL COMMENT '创建人',
|
||||
`update_user` bigint DEFAULT NULL COMMENT '更新人',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_purchase_pay_notice_order` (`purchase_pay_id`, `id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Web支付通知明细';
|
||||
6
sql/20260420_sys_country_code_alias_codes.sql
Normal file
6
sql/20260420_sys_country_code_alias_codes.sql
Normal file
@ -0,0 +1,6 @@
|
||||
ALTER TABLE `sys_country_code`
|
||||
ADD COLUMN `alias_codes` varchar(255) NOT NULL DEFAULT '' COMMENT '国家code别名集合(JSON数组)' AFTER `alias_name`;
|
||||
|
||||
UPDATE `sys_country_code`
|
||||
SET `alias_codes` = '["SA","KSA"]'
|
||||
WHERE `alpha_two` = 'SA' OR `alpha_three` = 'KSA';
|
||||
Loading…
x
Reference in New Issue
Block a user