feat: support h5 pay country configuration

This commit is contained in:
zhx 2026-06-24 11:56:58 +08:00
parent a92739a2bc
commit 22756c5e5b
20 changed files with 327 additions and 23 deletions

View File

@ -78,6 +78,9 @@ public interface PayCountryClientApi {
ResultResponse<Void> updateUsdExchangeRate(@RequestParam("id") Long id,
@RequestParam("rate") BigDecimal rate);
@PostMapping("/syncAllUsdExchangeRate")
ResultResponse<Integer> syncAllUsdExchangeRate();
@GetMapping("/updateCountryCurrency")
ResultResponse<Void> updateCountryCurrency(@RequestParam("id") Long id,
@RequestParam("currency") String currency);

View File

@ -7,6 +7,7 @@ import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.math.BigDecimal;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@ -46,6 +47,11 @@ public class SysPayApplicationCommodityCmd extends CommonCommand {
@JsonSerialize(using = ToStringSerializer.class)
private Long payCountryId;
/**
* 批量开通支付国家.
*/
private List<Long> payCountryIds;
/**
* 区域ID.
*/

View File

@ -52,6 +52,21 @@ public class SysPayApplicationCommodityDTO implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long payCountryId;
/**
* 支付国家.
*/
private CountryCodeDTO country;
/**
* 国家货币.
*/
private String currency;
/**
* USD 汇率.
*/
private BigDecimal usdExchangeRate;
/**
* 类型.
*/

View File

@ -86,6 +86,15 @@ public class SysPayOpenCountryController extends BaseController {
sysPayCountryService.updateUsdExchangeRate(id, rate);
}
/**
* 同步全部国家汇率.
*/
@OpsOperationReqLog("同步全部国家汇率")
@PostMapping("/sync-exchange-rate")
public Integer syncExchangeRate() {
return sysPayCountryService.syncAllUsdExchangeRate();
}
/**
* 修改国家货币code.
*/

View File

@ -53,6 +53,11 @@ public class SysPayCountryServiceImpl implements SysPayCountryService {
ResponseAssert.requiredSuccess(payCountryClient.updateUsdExchangeRate(id, rate));
}
@Override
public Integer syncAllUsdExchangeRate() {
return ResponseAssert.requiredSuccess(payCountryClient.syncAllUsdExchangeRate());
}
@Override
public void updateCountryCurrency(Long id, String currency) {
ResponseAssert.requiredSuccess(payCountryClient.updateCountryCurrency(id, currency));

View File

@ -44,6 +44,11 @@ public interface SysPayCountryService {
*/
void updateUsdExchangeRate(Long id, BigDecimal rate);
/**
* 同步全部开通支付国家美元汇率.
*/
Integer syncAllUsdExchangeRate();
/**
* 修改国家货币.
*/

View File

@ -24,6 +24,8 @@ import com.red.circle.order.infra.database.rds.service.pay.PayApplicationService
import com.red.circle.order.infra.database.rds.service.pay.PayChannelService;
import com.red.circle.order.infra.database.rds.service.pay.PayCountryChannelDetailsService;
import com.red.circle.order.infra.database.rds.service.pay.PayCountryService;
import com.red.circle.other.inner.endpoint.sys.SysCountryCodeClient;
import com.red.circle.other.inner.model.dto.sys.SysCountryCodeDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.text.StringUtils;
@ -52,6 +54,7 @@ public class PayWebApplicationCommodityV2QueryExe {
private final PayAppConvertor payAppConvertor;
private final PayCountryService payCountryService;
private final PayChannelService payChannelService;
private final SysCountryCodeClient sysCountryCodeClient;
private final PayApplicationService payApplicationService;
private final PayApplicationCommodityService payApplicationCommodityService;
private final PayCountryChannelDetailsService payCountryChannelDetailsService;
@ -65,12 +68,12 @@ public class PayWebApplicationCommodityV2QueryExe {
PayApplicationCO application = payAppConvertor
.toPayApplicationCO(payApplicationService.getById(cmd.getApplicationId()));
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, application);
SysCountryCodeDTO country = getCountryCode(payCountry);
List<PayApplicationCommodity> payApplicationCommodities = getPayApplicationCommodities(cmd);
if (CollectionUtils.isEmpty(payApplicationCommodities)) {
return new ApplicationCommodityCardV2CO()
.setApplication(application);
return baseCard(application, payCountry, country);
}
// 所有支持的渠道
@ -78,8 +81,7 @@ public class PayWebApplicationCommodityV2QueryExe {
.listChannelCode(cmd.getPayCountryId());
if (CollectionUtils.isEmpty(countryChannelDetails)) {
return new ApplicationCommodityCardV2CO()
.setApplication(application);
return baseCard(application, payCountry, country);
}
// 商品
@ -87,16 +89,14 @@ public class PayWebApplicationCommodityV2QueryExe {
payApplicationCommodities);
if (CollectionUtils.isEmpty(commodity)) {
return new ApplicationCommodityCardV2CO()
.setApplication(application);
return baseCard(application, payCountry, country);
}
// 过滤渠道限额范围
countryChannelDetails = filterCountryChannelLimit(countryChannelDetails, commodity);
if (CollectionUtils.isEmpty(countryChannelDetails)) {
return new ApplicationCommodityCardV2CO()
.setApplication(application);
return baseCard(application, payCountry, country);
}
// 渠道资料信息
@ -104,12 +104,10 @@ public class PayWebApplicationCommodityV2QueryExe {
.listByChannelCodes(countryChannelDetails.stream()
.map(PayCountryChannelDetails::getChannelCode).collect(Collectors.toSet()));
if (CollectionUtils.isEmpty(payChannels)) {
return new ApplicationCommodityCardV2CO()
.setApplication(application);
return baseCard(application, payCountry, country);
}
return new ApplicationCommodityCardV2CO()
.setApplication(application)
return baseCard(application, payCountry, country)
.setCommodity(commodity)
.setChannels(getPayChannels(payChannels, countryChannelDetails));
}
@ -165,9 +163,41 @@ public class PayWebApplicationCommodityV2QueryExe {
}
private PayCountry getPayCountry(PayWebApplicationCommodityCmd cmd) {
return Objects.isNull(cmd.getPayCountryId())
? payCountryService.getShelfSortMax()
: payCountryService.getById(cmd.getPayCountryId());
if (Objects.nonNull(cmd.getPayCountryId())) {
return payCountryService.getById(cmd.getPayCountryId());
}
if (StringUtils.isNotBlank(cmd.getCountryCode())) {
SysCountryCodeDTO country = ResponseAssert.requiredSuccess(
sysCountryCodeClient.getByCode(cmd.getCountryCode().trim().toUpperCase())
);
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, country);
return payCountryService.query()
.eq(PayCountry::getCountryId, country.getId())
.eq(PayCountry::getShelf, Boolean.TRUE)
.orderByDesc(PayCountry::getSort)
.last(com.red.circle.framework.mybatis.constant.PageConstant.LIMIT_ONE)
.getOne();
}
return payCountryService.getShelfSortMax();
}
private SysCountryCodeDTO getCountryCode(PayCountry payCountry) {
SysCountryCodeDTO country = ResponseAssert.requiredSuccess(
sysCountryCodeClient.getById(payCountry.getCountryId()));
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, country);
return country;
}
private ApplicationCommodityCardV2CO baseCard(PayApplicationCO application, PayCountry payCountry,
SysCountryCodeDTO country) {
return new ApplicationCommodityCardV2CO()
.setApplication(application)
.setPayCountryId(Objects.toString(payCountry.getId()))
.setCountryCode(country.getAlphaTwo())
.setCountryName(country.getCountryName())
.setCurrencyCode(payCountry.getCurrency());
}
private List<PayChannelDetailsCO> getPayChannels(List<PayChannel> payChannels,

View File

@ -1,6 +1,7 @@
package com.red.circle.order.app.command.pay.web;
import com.red.circle.common.business.core.amount.PayAmountArithmeticUtils;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.order.app.dto.clientobject.pay.PayCountryCO;
@ -50,7 +51,7 @@ public class PayWebH5OptionsQryExe {
public PayWebH5ContextCO context(PayWebUserCmd cmd) {
defaultType(cmd);
UserProfileAndCountryCO source = userProfileAndCountryQueryExe.execute(cmd);
UserProfileAndCountryCO source = userProfileAndCountryQueryExe.h5Context(cmd);
WebSiteUseProfileCO userProfile = source.getUserProfile();
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, userProfile);
@ -63,6 +64,8 @@ public class PayWebH5OptionsQryExe {
.setAvatar(userProfile.getUserAvatar())
.setAccount(userProfile.getAccount())
.setSysOrigin(userProfile.getSysOrigin())
.setCountryName(userProfile.getCountryName())
.setCountryCode(userProfile.getCountryCode())
.setFreightAgent(userProfile.getFreightAgent())
.setSuperFreightAgent(userProfile.getSuperFreightAgent())
.setAudienceType(resolveAudienceType(userProfile)))
@ -75,9 +78,7 @@ public class PayWebH5OptionsQryExe {
PayApplication application = payApplicationService.getById(cmd.getApplicationId());
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, application);
PayCountry payCountry = Objects.isNull(cmd.getPayCountryId())
? payCountryService.getShelfSortMax()
: payCountryService.getById(cmd.getPayCountryId());
PayCountry payCountry = resolvePayCountry(cmd);
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, payCountry);
SysCountryCodeDTO country = ResponseAssert.requiredSuccess(
@ -114,6 +115,32 @@ public class PayWebH5OptionsQryExe {
.collect(Collectors.toList()));
}
private PayCountry resolvePayCountry(PayWebH5OptionsCmd cmd) {
if (Objects.nonNull(cmd.getPayCountryId())) {
// H5 后续下单要使用同一个 payCountryId显式传 id 时只校验后台是否仍存在且上架
PayCountry payCountry = payCountryService.getById(cmd.getPayCountryId());
return Objects.nonNull(payCountry) && Boolean.TRUE.equals(payCountry.getShelf())
? payCountry
: null;
}
if (StringUtils.isNotBlank(cmd.getCountryCode())) {
// 支付国家是否展示由本地 JSON 决定服务端只把 JSON 国家码解析为后台支付国家用于汇率和商品快照
SysCountryCodeDTO country = ResponseAssert.requiredSuccess(
sysCountryCodeClient.getByCode(cmd.getCountryCode().trim().toUpperCase())
);
ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, country);
return payCountryService.query()
.eq(PayCountry::getCountryId, country.getId())
.eq(PayCountry::getShelf, Boolean.TRUE)
.orderByDesc(PayCountry::getSort)
.last(PageConstant.LIMIT_ONE)
.getOne();
}
return payCountryService.getShelfSortMax();
}
private PayWebH5ProductCO toProduct(PayApplicationCommodity commodity, PayCountry payCountry) {
BigDecimal amount = PayAmountArithmeticUtils.multiplyUpNotPoint(
commodity.getAmountUsd(),

View File

@ -69,6 +69,9 @@ public class PayWebPlaceAnOrderCmdExe {
// 未知的应用
ResponseAssert.notNull(PayErrorCode.UNKNOWN_APPLICATION, application);
PayApplicationCommodity commodity = getAppCommodity(cmd);
ResponseAssert.isTrue(CommonErrorCode.NOT_FOUND_MAPPING_INFO,
Objects.isNull(commodity.getPayCountryId())
|| Objects.equals(commodity.getPayCountryId(), cmd.getPayCountryId()));
PayCountryChannelDetails channelDetails = payCountryChannelDetailsService
.getSuggestScoreMax(cmd.getPayCountryId(), cmd.getChannelCode(),

View File

@ -96,6 +96,32 @@ public class UserProfileAndCountryQueryExe {
}
public UserProfileAndCountryCO h5Context(PayWebUserCmd cmd) {
UserProfileDTO userProfile = getUserProfile(cmd);
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, userProfile);
if (Objects.equals(cmd.getType(), PayApplicationCommodityType.FREIGHT_GOLD)) {
ResponseAssert.isTrue(UserErrorCode.USER_INFO_NOT_FOUND,
ResponseAssert.requiredSuccess(freightGoldClient.existsBalance(userProfile.getId())));
}
WebSiteUseProfileCO webSiteUseProfile = WebSiteUseProfileCO
.toWebSiteUseProfileCO(userProfile);
webSiteUseProfile.setAccount(userProfile.actualAccount());
// H5 的支付国家开关由 app JSON 控制服务端 context 只确认账号和用户所在区域
// 这里不读取 OPEN_PAY_COUNTRY 关系避免用户 region 未配置支付国家时阻断商品查询
String regionId = ResponseAssert.requiredSuccess(
userRegionClient.getRegionId(userProfile.getId())
);
return new UserProfileAndCountryCO()
.setUserProfile(webSiteUseProfile)
.setRegionId(regionId);
}
private UserProfileDTO getUserProfile(PayWebUserCmd cmd) {
if (StringUtils.isNotBlank(cmd.getAccount()) && StringUtils.isNotBlank(cmd.getSysOrigin())) {
return ResponseAssert.requiredSuccess(

View File

@ -1,5 +1,6 @@
package com.red.circle.order.app.dto.clientobject.pay;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.red.circle.framework.dto.ClientObject;
import java.util.List;
import lombok.Data;
@ -23,6 +24,30 @@ public class ApplicationCommodityCardV2CO extends ClientObject {
*/
private PayApplicationCO application;
/**
* 当前支付国家ID.
*/
@JsonProperty("pay_country_id")
private String payCountryId;
/**
* 当前国家编码.
*/
@JsonProperty("country_code")
private String countryCode;
/**
* 当前国家名称.
*/
@JsonProperty("country_name")
private String countryName;
/**
* 当前国家货币.
*/
@JsonProperty("currency_code")
private String currencyCode;
/**
* 渠道商品信息.
*/

View File

@ -37,6 +37,12 @@ public class PayWebH5AccountCO extends ClientObject {
@JsonProperty("sys_origin")
private String sysOrigin;
@JsonProperty("country_name")
private String countryName;
@JsonProperty("country_code")
private String countryCode;
@JsonProperty("audience_type")
private String audienceType;

View File

@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* H5 充值页上下文账号和国家都来自 Aslan 服务端前端只拿它做展示和后续商品查询条件
* H5 充值页上下文账号来自 Aslan 服务端支付国家由 H5 app JSON 决定服务端只返回兼容字段
*
* @author tf
*/

View File

@ -49,6 +49,16 @@ public class WebSiteUseProfileCO extends ClientObject {
*/
private String sysOrigin;
/**
* 用户国家名称.
*/
private String countryName;
/**
* 用户国家编码.
*/
private String countryCode;
/**
* 是否金币代理.
*/
@ -69,6 +79,8 @@ public class WebSiteUseProfileCO extends ClientObject {
.setUserNickname(userProfile.getUserNickname())
.setAccount(userProfile.getAccount())
.setSysOrigin(userProfile.getOriginSys())
.setCountryName(userProfile.getCountryName())
.setCountryCode(userProfile.getCountryCode())
.setFreightAgent(userProfile.getIsFreightAgent())
.setSuperFreightAgent(userProfile.getIsSuperFreightAgent());
}

View File

@ -32,6 +32,11 @@ public class PayWebApplicationCommodityCmd extends AppExtCommand {
*/
private Long payCountryId;
/**
* 国家码.
*/
private String countryCode;
/**
* 金币类型.
*/

View File

@ -8,7 +8,7 @@ import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* H5 商品查询命令商品类型和国家来自已确认账号上下文
* H5 商品查询命令商品类型来自页面配置支付国家来自 H5 app JSON 的国家码或已解析的 payCountryId
*
* @author tf
*/
@ -24,6 +24,8 @@ public class PayWebH5OptionsCmd extends Command {
private Long payCountryId;
private String countryCode;
private Long userId;
private String regionId;

View File

@ -120,6 +120,11 @@ public class PayCountryClientEndpoint implements PayCountryClientApi {
return ResultResponse.success();
}
@Override
public ResultResponse<Integer> syncAllUsdExchangeRate() {
return ResultResponse.success(payCountryClientService.syncAllUsdExchangeRate());
}
@Override
public ResultResponse<Void> updateCountryCurrency(Long id, String currency) {
payCountryClientService.updateCountryCurrency(id, currency);

View File

@ -51,6 +51,8 @@ public interface PayCountryClientService {
void updateUsdExchangeRate(Long id, BigDecimal rate);
Integer syncAllUsdExchangeRate();
void updateCountryCurrency(Long id, String currency);
void updateSort(Long id, Integer sort);

View File

@ -3,23 +3,30 @@ package com.red.circle.order.inner.service.impl;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.order.infra.database.rds.entity.pay.PayApplication;
import com.red.circle.order.infra.database.rds.entity.pay.PayApplicationCommodity;
import com.red.circle.order.infra.database.rds.entity.pay.PayCountry;
import com.red.circle.order.infra.database.rds.service.pay.PayApplicationCommodityService;
import com.red.circle.order.infra.database.rds.service.pay.PayApplicationService;
import com.red.circle.order.infra.database.rds.service.pay.PayCountryService;
import com.red.circle.order.inner.convertor.WebPayInnerConvertor;
import com.red.circle.order.inner.model.cmd.SysPayApplicationCommodityCmd;
import com.red.circle.order.inner.model.cmd.SysPayApplicationCommodityQryCmd;
import com.red.circle.order.inner.model.dto.SysPayApplicationCommodityDTO;
import com.red.circle.order.inner.model.dto.SysPayApplicationDTO;
import com.red.circle.order.inner.service.PayApplicationClientService;
import com.red.circle.other.inner.endpoint.sys.SysCountryCodeClient;
import com.red.circle.other.inner.model.dto.sys.SysCountryCodeDTO;
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 com.red.circle.other.inner.endpoint.user.region.RegionConfigClient;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -34,6 +41,8 @@ import org.springframework.stereotype.Service;
public class PayApplicationClientServiceImpl implements PayApplicationClientService {
private final RegionConfigClient regionConfigClient;
private final PayCountryService payCountryService;
private final SysCountryCodeClient sysCountryCodeClient;
private final WebPayInnerConvertor webPayInnerConvertor;
private final PayApplicationService payApplicationService;
private final PayApplicationCommodityService payApplicationCommodityService;
@ -88,12 +97,21 @@ public class PayApplicationClientServiceImpl implements PayApplicationClientServ
}
Map<String, String> mapRegionName = getMapRegionName(commodityPage);
Map<Long, PayCountry> mapPayCountry = getMapPayCountry(commodityPage);
Map<Long, SysCountryCodeDTO> mapCountryCode = getMapCountryCode(mapPayCountry);
return commodityPage.convert(commodity -> {
if (StringUtils.isNotBlank(commodity.getRegionId())) {
commodity.setRegionName(mapRegionName.get(commodity.getRegionId()));
}
PayCountry payCountry = mapPayCountry.get(commodity.getPayCountryId());
if (Objects.nonNull(payCountry)) {
commodity.setCurrency(payCountry.getCurrency());
commodity.setUsdExchangeRate(payCountry.getUsdExchangeRate());
commodity.setCountry(webPayInnerConvertor.toCountryCodeDTO(
mapCountryCode.get(payCountry.getCountryId())));
}
return commodity;
});
}
@ -106,10 +124,75 @@ public class PayApplicationClientServiceImpl implements PayApplicationClientServ
Collectors.toSet())));
}
private Map<Long, PayCountry> getMapPayCountry(
PageResult<SysPayApplicationCommodityDTO> commodityPage) {
Set<Long> payCountryIds = commodityPage.getRecords().stream()
.map(SysPayApplicationCommodityDTO::getPayCountryId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (CollectionUtils.isEmpty(payCountryIds)) {
return CollectionUtils.newHashMap();
}
return payCountryService.mapByIds(payCountryIds);
}
private Map<Long, SysCountryCodeDTO> getMapCountryCode(Map<Long, PayCountry> mapPayCountry) {
if (CollectionUtils.isEmpty(mapPayCountry)) {
return CollectionUtils.newHashMap();
}
return ResponseAssert.requiredSuccess(
sysCountryCodeClient.mapByIdes(mapPayCountry.values().stream()
.map(PayCountry::getCountryId)
.filter(Objects::nonNull)
.collect(Collectors.toSet()))
);
}
@Override
public void addOrUpdateCommodity(SysPayApplicationCommodityCmd param) {
payApplicationCommodityService.saveOrUpdate(
webPayInnerConvertor.toPayApplicationCommodity(param));
if (Objects.nonNull(param.getId()) || CollectionUtils.isEmpty(param.getPayCountryIds())) {
payApplicationCommodityService.saveOrUpdate(
webPayInnerConvertor.toPayApplicationCommodity(param));
return;
}
List<PayApplicationCommodity> commodities = param.getPayCountryIds().stream()
.filter(Objects::nonNull)
.distinct()
.map(payCountryId -> {
PayApplicationCommodity commodity = getOrCreateCommodity(param, payCountryId);
commodity.setApplicationId(param.getApplicationId());
commodity.setPayCountryId(payCountryId);
commodity.setRegionId(StringUtils.isBlankOrElse(param.getRegionId(), ""));
commodity.setType(param.getType());
commodity.setContent(param.getContent());
commodity.setAwardContent(StringUtils.isBlankOrElse(param.getAwardContent(), "0"));
commodity.setAmountUsd(param.getAmountUsd());
commodity.setShelf(Boolean.TRUE.equals(param.getShelf()));
commodity.setUpdateTime(TimestampUtils.now());
if (Objects.isNull(commodity.getId())) {
commodity.setCreateTime(TimestampUtils.now());
}
return commodity;
})
.collect(Collectors.toList());
if (CollectionUtils.isNotEmpty(commodities)) {
payApplicationCommodityService.saveOrUpdateBatch(commodities);
}
}
private PayApplicationCommodity getOrCreateCommodity(SysPayApplicationCommodityCmd param,
Long payCountryId) {
PayApplicationCommodity commodity = payApplicationCommodityService.query()
.eq(PayApplicationCommodity::getApplicationId, param.getApplicationId())
.eq(PayApplicationCommodity::getPayCountryId, payCountryId)
.eq(PayApplicationCommodity::getRegionId, StringUtils.isBlankOrElse(param.getRegionId(), ""))
.eq(PayApplicationCommodity::getType, param.getType())
.eq(PayApplicationCommodity::getAmountUsd, param.getAmountUsd())
.last(PageConstant.LIMIT_ONE)
.getOne();
return Objects.nonNull(commodity) ? commodity : new PayApplicationCommodity();
}
@Override

View File

@ -5,6 +5,7 @@ import com.google.api.client.util.Maps;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.order.app.command.pay.web.strategy.PayPlaceAnOrderService;
import com.red.circle.order.infra.database.rds.entity.pay.PayCountry;
import com.red.circle.order.infra.database.rds.entity.pay.PayCountryChannel;
import com.red.circle.order.infra.database.rds.entity.pay.PayCountryChannelDetails;
@ -31,9 +32,11 @@ import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
@ -43,9 +46,11 @@ import org.springframework.stereotype.Service;
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class PayCountryClientServiceImpl implements PayCountryClientService {
private final PayCountryService payCountryService;
private final PayPlaceAnOrderService payPlaceAnOrderService;
private final SysCountryCodeClient countryCodeClient;
private final WebPayInnerConvertor webPayInnerConvertor;
private final RegionRelationClient regionRelationClient;
@ -246,6 +251,36 @@ public class PayCountryClientServiceImpl implements PayCountryClientService {
payCountryService.updateUsdExchangeRate(id, rate);
}
@Override
public Integer syncAllUsdExchangeRate() {
List<PayCountry> payCountries = payCountryService.listOpenPayCountry(null);
if (CollectionUtils.isEmpty(payCountries)) {
return 0;
}
int successCount = 0;
for (PayCountry payCountry : payCountries) {
if (StringUtils.isBlank(payCountry.getCurrency())) {
log.warn("Skip exchange rate sync because currency is blank, payCountryId={}",
payCountry.getId());
continue;
}
BigDecimal rate = "USD".equalsIgnoreCase(payCountry.getCurrency())
? BigDecimal.ONE
: payPlaceAnOrderService.getRealTimeExchangeRate("USD", payCountry.getCurrency());
if (Objects.isNull(rate)) {
log.warn("Skip exchange rate sync because realtime rate is empty, payCountryId={}, currency={}",
payCountry.getId(), payCountry.getCurrency());
continue;
}
payCountryService.updateUsdExchangeRate(payCountry.getId(), rate);
successCount++;
}
return successCount;
}
@Override
public void updateCountryCurrency(Long id, String currency) {
payCountryService.updateCountryCurrency(id, currency);