首冲奖励
This commit is contained in:
parent
8e37a3d333
commit
e897d635ea
@ -0,0 +1,36 @@
|
||||
package com.red.circle.mq.business.model.event.pay;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 通用充值成功事件。
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RechargeSuccessEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String eventId;
|
||||
private String sysOrigin;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long userId;
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long amountCents;
|
||||
|
||||
private String amountUsd;
|
||||
private String currency;
|
||||
private String payPlatform;
|
||||
private String paymentMethod;
|
||||
private String sourceOrderId;
|
||||
private String orderId;
|
||||
private String occurredAt;
|
||||
private Map<String, Object> payload;
|
||||
}
|
||||
@ -17,13 +17,18 @@ public interface QueueNameConstant {
|
||||
*/
|
||||
String LOGIN_REGISTER = "LOGIN_REGISTER";
|
||||
|
||||
/**
|
||||
* 购买成功
|
||||
*/
|
||||
String BUY_SUCCESS = "BUY_SUCCESS";
|
||||
|
||||
/**
|
||||
* 视频语音房间会话
|
||||
/**
|
||||
* 购买成功
|
||||
*/
|
||||
String BUY_SUCCESS = "BUY_SUCCESS";
|
||||
|
||||
/**
|
||||
* 通用充值成功。
|
||||
*/
|
||||
String RECHARGE_SUCCESS = "RECHARGE_SUCCESS";
|
||||
|
||||
/**
|
||||
* 视频语音房间会话
|
||||
*/
|
||||
String LIVE_VOICE_SESSION = "LIVE_VOICE_SESSION";
|
||||
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
package com.red.circle.mq.rocket.business.streams;
|
||||
|
||||
import com.red.circle.mq.rocket.business.constant.QueueNameConstant;
|
||||
|
||||
/**
|
||||
* 通用充值成功事件。
|
||||
*/
|
||||
public interface RechargeSuccessSink {
|
||||
|
||||
String INPUT = QueueNameConstant.RECHARGE_SUCCESS;
|
||||
String TAG = "recharge_success_v1";
|
||||
}
|
||||
@ -8,8 +8,9 @@ import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
||||
import com.red.circle.framework.dto.ResultResponse;
|
||||
import com.red.circle.framework.web.props.EnvProperties;
|
||||
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
|
||||
import com.red.circle.order.app.command.pay.web.strategy.PayEnv;
|
||||
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
|
||||
import com.red.circle.order.app.common.task.RechargeSuccessEventPublisher;
|
||||
import com.red.circle.order.app.command.pay.web.strategy.PayEnv;
|
||||
import com.red.circle.order.domain.gateway.UserRechargeCountGateway;
|
||||
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseCollectionReceiptService;
|
||||
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseDetailsService;
|
||||
@ -76,9 +77,10 @@ public class InAppPurchaseCommon {
|
||||
private final OrderPurchaseHistoryService orderPurchaseHistoryService;
|
||||
private final InAppPurchaseCollectionReceiptService inAppPurchaseCollectionReceiptService;
|
||||
private final UserLevelClient userLevelClient;
|
||||
private final PropsActivityClient propsActivityClient;
|
||||
private final PropsActivityClient propsActivityClient;
|
||||
private final UserOneTimeTaskClient userOneTimeTaskClient;
|
||||
private final UserProfileClient userProfileClient;
|
||||
private final RechargeSuccessEventPublisher rechargeSuccessEventPublisher;
|
||||
|
||||
public void inAppPurchaseReceipt(InAppPurchaseDetails order) {
|
||||
inAppPurchaseReceipt(order,
|
||||
@ -192,13 +194,15 @@ public class InAppPurchaseCommon {
|
||||
userSvipClient.incrIntegral(order.getAcceptUserId(),
|
||||
amount.longValue());
|
||||
|
||||
// 被邀请人充值邀请人获得佣金
|
||||
inviteUserClient.processRechargeCommission(amount,
|
||||
order.getSysOrigin(), order.getAcceptUserId());
|
||||
|
||||
// 发送首充奖励
|
||||
completedFirstCharge(order.getAcceptUserId(), order.getSysOrigin());
|
||||
}
|
||||
// 被邀请人充值邀请人获得佣金
|
||||
inviteUserClient.processRechargeCommission(amount,
|
||||
order.getSysOrigin(), order.getAcceptUserId());
|
||||
|
||||
rechargeSuccessEventPublisher.reportPaymentRecharge(order);
|
||||
|
||||
// 发送首充奖励
|
||||
completedFirstCharge(order.getAcceptUserId(), order.getSysOrigin());
|
||||
}
|
||||
|
||||
private void completedFirstCharge(Long userId, String sysOrigin) {
|
||||
UserProfileDTO userProfileDTO = userProfileClient.getByUserId(userId).getBody();
|
||||
|
||||
@ -0,0 +1,214 @@
|
||||
package com.red.circle.order.app.common.task;
|
||||
|
||||
import com.red.circle.component.mq.MessageEvent;
|
||||
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
|
||||
import com.red.circle.mq.business.model.event.pay.RechargeSuccessEvent;
|
||||
import com.red.circle.mq.rocket.business.service.MessageSenderService;
|
||||
import com.red.circle.mq.rocket.business.streams.RechargeSuccessSink;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
|
||||
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseProduct;
|
||||
import com.red.circle.order.inner.model.enums.PayApplicationCommodityType;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class RechargeSuccessEventPublisher {
|
||||
|
||||
private static final String GOOGLE = "GOOGLE";
|
||||
private static final String APPLE = "APPLE";
|
||||
private static final String THIRD_PARTY = "THIRD_PARTY";
|
||||
private static final String UNKNOWN = "UNKNOWN";
|
||||
|
||||
private final ObjectProvider<MessageSenderService> messageSenderServiceProvider;
|
||||
|
||||
@Value("${recharge.success.mq.enabled:true}")
|
||||
private boolean mqEnabled;
|
||||
|
||||
@Value("${recharge.success.mq.topic:RC_DEFAULT_APP_ORDINARY}")
|
||||
private String mqTopic;
|
||||
|
||||
@Value("${recharge.success.mq.tag:" + RechargeSuccessSink.TAG + "}")
|
||||
private String mqTag;
|
||||
|
||||
public RechargeSuccessEventPublisher(ObjectProvider<MessageSenderService> messageSenderServiceProvider) {
|
||||
this.messageSenderServiceProvider = messageSenderServiceProvider;
|
||||
}
|
||||
|
||||
public void reportAppPurchaseRecharge(BuySuccessEvent event) {
|
||||
if (Objects.isNull(event)) {
|
||||
return;
|
||||
}
|
||||
Long userId = event.getAcceptUserId();
|
||||
Long purchaseHistoryId = event.getPurchaseHistoryId();
|
||||
BigDecimal amountUsd = Objects.nonNull(event.getProductConfig())
|
||||
? event.getProductConfig().getUnitPrice()
|
||||
: null;
|
||||
Long amountCents = toCents(amountUsd);
|
||||
if (Objects.isNull(userId) || Objects.isNull(purchaseHistoryId) || !positive(amountCents)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("payerUserId", event.getUserId());
|
||||
payload.put("acceptUserId", userId);
|
||||
payload.put("purchaseHistoryId", purchaseHistoryId);
|
||||
payload.put("candyQuantity", event.getCandyQuantity());
|
||||
payload.put("platform", event.getPlatform());
|
||||
payload.put("payPlatform", event.getPayPlatform());
|
||||
|
||||
String sourceOrderId = String.valueOf(purchaseHistoryId);
|
||||
String payPlatform = normalizePayPlatform(defaultIfBlank(event.getPayPlatform(), event.getPlatform()));
|
||||
String paymentMethod = classifyPaymentMethod(payPlatform);
|
||||
publish(new RechargeSuccessEvent()
|
||||
.setEventId("RECHARGE_SUCCESS:" + paymentMethod + ":" + sourceOrderId)
|
||||
.setSysOrigin(event.getSysOrigin())
|
||||
.setUserId(userId)
|
||||
.setAmountCents(amountCents)
|
||||
.setAmountUsd(formatAmount(amountUsd))
|
||||
.setCurrency("USD")
|
||||
.setPayPlatform(payPlatform)
|
||||
.setPaymentMethod(paymentMethod)
|
||||
.setSourceOrderId(sourceOrderId)
|
||||
.setOrderId(sourceOrderId)
|
||||
.setOccurredAt(toInstantString(event.getBuyDateTime()))
|
||||
.setPayload(payload));
|
||||
}
|
||||
|
||||
public void reportPaymentRecharge(InAppPurchaseDetails order) {
|
||||
if (Objects.isNull(order) || !order.receiptTypeEqPayment()) {
|
||||
return;
|
||||
}
|
||||
InAppPurchaseProduct product = order.firstProduct();
|
||||
if (Objects.isNull(product) || !PayApplicationCommodityType.GOLD.eq(product.getCode())) {
|
||||
return;
|
||||
}
|
||||
String payPlatform = normalizePayPlatform(Objects.nonNull(order.getFactory()) ? order.getFactory().getFactoryCode() : "");
|
||||
String paymentMethod = classifyPaymentMethod(payPlatform);
|
||||
|
||||
BigDecimal amountUsd = firstPositive(order.getAmountUsd(), product.getAmountUsd());
|
||||
Long amountCents = toCents(amountUsd);
|
||||
if (Objects.isNull(order.getAcceptUserId()) || isBlank(order.getId()) || !positive(amountCents)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> payload = new HashMap<>();
|
||||
payload.put("trackId", order.getTrackId());
|
||||
payload.put("sourceOrderId", order.getId());
|
||||
payload.put("orderId", order.getOrderId());
|
||||
payload.put("factoryCode", payPlatform);
|
||||
payload.put("factoryChannelCode", Objects.nonNull(order.getFactory()) ? order.getFactory().getFactoryChannelCode() : null);
|
||||
payload.put("platform", Objects.nonNull(order.getFactory()) ? order.getFactory().getPlatform() : null);
|
||||
payload.put("productCode", product.getCode());
|
||||
payload.put("productContent", product.getContent());
|
||||
|
||||
publish(new RechargeSuccessEvent()
|
||||
.setEventId("RECHARGE_SUCCESS:" + paymentMethod + ":" + payPlatform + ":" + order.getId())
|
||||
.setSysOrigin(order.getSysOrigin())
|
||||
.setUserId(order.getAcceptUserId())
|
||||
.setAmountCents(amountCents)
|
||||
.setAmountUsd(formatAmount(amountUsd))
|
||||
.setCurrency(defaultIfBlank(order.getCurrency(), "USD"))
|
||||
.setPayPlatform(payPlatform)
|
||||
.setPaymentMethod(paymentMethod)
|
||||
.setSourceOrderId(order.getId())
|
||||
.setOrderId(defaultIfBlank(order.getOrderId(), order.getId()))
|
||||
.setOccurredAt(firstTime(order.getPurchaseDateMs(), order.getUpdateTime(), order.getCreateTime()))
|
||||
.setPayload(payload));
|
||||
}
|
||||
|
||||
private void publish(RechargeSuccessEvent event) {
|
||||
if (!mqEnabled) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
MessageSenderService senderService = messageSenderServiceProvider.getIfAvailable();
|
||||
if (Objects.isNull(senderService)) {
|
||||
log.warn("Recharge success mq sender missing, skip event report. eventId={}", event.getEventId());
|
||||
return;
|
||||
}
|
||||
senderService.sendEventMessage(MessageEvent.builder()
|
||||
.consumeId(event.getEventId())
|
||||
.topicString(defaultIfBlank(mqTopic, "RC_DEFAULT_APP_ORDINARY"))
|
||||
.tag(defaultIfBlank(mqTag, RechargeSuccessSink.TAG))
|
||||
.body(event)
|
||||
.build());
|
||||
} catch (Exception e) {
|
||||
log.warn("Recharge success mq report error. eventId={}", event.getEventId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizePayPlatform(String value) {
|
||||
String normalized = Objects.toString(value, "").trim().toUpperCase();
|
||||
return normalized.isEmpty() ? UNKNOWN : normalized;
|
||||
}
|
||||
|
||||
private String classifyPaymentMethod(String payPlatform) {
|
||||
if (Objects.equals(GOOGLE, payPlatform)) {
|
||||
return GOOGLE;
|
||||
}
|
||||
if (Objects.equals(APPLE, payPlatform)) {
|
||||
return APPLE;
|
||||
}
|
||||
if (Objects.equals(UNKNOWN, payPlatform)) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
return THIRD_PARTY;
|
||||
}
|
||||
|
||||
private Long toCents(BigDecimal amount) {
|
||||
if (Objects.isNull(amount) || amount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return null;
|
||||
}
|
||||
return amount.multiply(BigDecimal.valueOf(100)).setScale(0, RoundingMode.HALF_UP).longValue();
|
||||
}
|
||||
|
||||
private BigDecimal firstPositive(BigDecimal first, BigDecimal second) {
|
||||
if (Objects.nonNull(first) && first.compareTo(BigDecimal.ZERO) > 0) {
|
||||
return first;
|
||||
}
|
||||
return second;
|
||||
}
|
||||
|
||||
private boolean positive(Long value) {
|
||||
return Objects.nonNull(value) && value > 0;
|
||||
}
|
||||
|
||||
private String toInstantString(Timestamp timestamp) {
|
||||
return Objects.nonNull(timestamp) ? timestamp.toInstant().toString() : Instant.now().toString();
|
||||
}
|
||||
|
||||
private String firstTime(Timestamp first, Timestamp second, Timestamp third) {
|
||||
if (Objects.nonNull(first)) {
|
||||
return first.toInstant().toString();
|
||||
}
|
||||
if (Objects.nonNull(second)) {
|
||||
return second.toInstant().toString();
|
||||
}
|
||||
if (Objects.nonNull(third)) {
|
||||
return third.toInstant().toString();
|
||||
}
|
||||
return Instant.now().toString();
|
||||
}
|
||||
|
||||
private String formatAmount(BigDecimal amount) {
|
||||
return Objects.isNull(amount) ? null : amount.stripTrailingZeros().toPlainString();
|
||||
}
|
||||
|
||||
private String defaultIfBlank(String value, String fallback) {
|
||||
return isBlank(value) ? fallback : value.trim();
|
||||
}
|
||||
|
||||
private boolean isBlank(String value) {
|
||||
return Objects.toString(value, "").trim().isEmpty();
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,7 @@ import com.red.circle.framework.dto.ResultResponse;
|
||||
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
|
||||
import com.red.circle.mq.business.model.event.pay.PurchaseProductEvent;
|
||||
import com.red.circle.mq.rocket.business.streams.BuySuccessSink;
|
||||
import com.red.circle.order.app.common.task.RechargeSuccessEventPublisher;
|
||||
import com.red.circle.order.app.common.task.TaskCenterGoClient;
|
||||
import com.red.circle.other.inner.endpoint.activity.CumulativeRechargeClient;
|
||||
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
|
||||
@ -71,6 +72,7 @@ public class BuySuccessListener implements MessageListener {
|
||||
private final CumulativeRechargeClient cumulativeRechargeClient;
|
||||
private final RedisService redisService;
|
||||
private final TaskCenterGoClient taskCenterGoClient;
|
||||
private final RechargeSuccessEventPublisher rechargeSuccessEventPublisher;
|
||||
|
||||
@Override
|
||||
public Action consume(ConsumerMessage message) {
|
||||
@ -133,6 +135,7 @@ public class BuySuccessListener implements MessageListener {
|
||||
eventBody.getPlatform(),
|
||||
eventBody.getPayPlatform(),
|
||||
Objects.nonNull(eventBody.getBuyDateTime()) ? eventBody.getBuyDateTime().toInstant() : null);
|
||||
rechargeSuccessEventPublisher.reportAppPurchaseRecharge(eventBody);
|
||||
|
||||
userExpandClient.updatePurchasingToTrue(eventBody.getUserId());
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user