order 和 console

This commit is contained in:
hy001 2026-06-25 16:13:09 +08:00
parent 1826aa10ab
commit c39dac772a
12 changed files with 432 additions and 147 deletions

View File

@ -6,7 +6,9 @@ import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryCurrencyRateSyncCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd;
import com.red.circle.order.inner.model.dto.PayCountryCurrencyRateSyncDTO;
import com.red.circle.order.inner.model.dto.PayCountryDTO; import com.red.circle.order.inner.model.dto.PayCountryDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO;
@ -88,6 +90,10 @@ public interface PayCountryClientApi {
@GetMapping("/shelf") @GetMapping("/shelf")
ResultResponse<Void> shelf(@RequestParam("id") Long id, @RequestParam("shelf") Boolean shelf); ResultResponse<Void> shelf(@RequestParam("id") Long id, @RequestParam("shelf") Boolean shelf);
@PostMapping("/syncCurrencyRates")
ResultResponse<PayCountryCurrencyRateSyncDTO> syncCurrencyRates(
@RequestBody SysPayCountryCurrencyRateSyncCmd cmd);
@GetMapping("/listPayCountryByRegionId") @GetMapping("/listPayCountryByRegionId")
ResultResponse<List<PayCountryDTO>> listPayCountryByRegionId( ResultResponse<List<PayCountryDTO>> listPayCountryByRegionId(
@RequestParam("regionId") String regionId); @RequestParam("regionId") String regionId);

View File

@ -0,0 +1,33 @@
package com.red.circle.order.inner.model.cmd;
import com.red.circle.framework.core.dto.CommonCommand;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 支付国家货币汇率同步命令.
*
* @author system
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class SysPayCountryCurrencyRateSyncCmd extends CommonCommand {
private static final long serialVersionUID = 1L;
/**
* 上浮比例5 表示在实时汇率基础上增加 5%.
*/
@NotNull
@DecimalMin("0")
@DecimalMax("100")
@Digits(integer = 3, fraction = 4)
private BigDecimal markupPercent;
}

View File

@ -0,0 +1,47 @@
package com.red.circle.order.inner.model.dto;
import com.red.circle.framework.dto.DTO;
import java.io.Serial;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 支付国家货币汇率同步结果.
*
* @author system
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class PayCountryCurrencyRateSyncDTO extends DTO {
@Serial
private static final long serialVersionUID = 1L;
/**
* 参与同步的支付国家数量.
*/
private Integer totalCount;
/**
* 已更新的支付国家数量.
*/
private Integer updatedCount;
/**
* 跳过的支付国家数量.
*/
private Integer skippedCount;
/**
* 汇率来源.
*/
private String sourceName;
/**
* 被跳过的国家说明.
*/
private List<String> skippedCountries;
}

View File

@ -6,7 +6,9 @@ import com.red.circle.console.infra.annotations.OpsOperationReqLog;
import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.web.controller.BaseController; import com.red.circle.framework.web.controller.BaseController;
import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryCurrencyRateSyncCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd;
import com.red.circle.order.inner.model.dto.PayCountryCurrencyRateSyncDTO;
import com.red.circle.order.inner.model.dto.PayCountryDTO; import com.red.circle.order.inner.model.dto.PayCountryDTO;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashSet; import java.util.HashSet;
@ -116,5 +118,14 @@ public class SysPayOpenCountryController extends BaseController {
sysPayCountryService.shelf(id, shelf); sysPayCountryService.shelf(id, shelf);
} }
/**
* 同步全球支付国家货币和实时汇率.
*/
@OpsOperationReqLog("同步全球支付国家货币汇率")
@PostMapping("/sync-currency-rates")
public PayCountryCurrencyRateSyncDTO syncCurrencyRates(
@RequestBody @Validated SysPayCountryCurrencyRateSyncCmd cmd) {
return sysPayCountryService.syncCurrencyRates(cmd);
}
} }

View File

@ -4,7 +4,9 @@ import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.dto.PageResult;
import com.red.circle.order.inner.endpoint.PayCountryClient; import com.red.circle.order.inner.endpoint.PayCountryClient;
import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryCurrencyRateSyncCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd;
import com.red.circle.order.inner.model.dto.PayCountryCurrencyRateSyncDTO;
import com.red.circle.order.inner.model.dto.PayCountryDTO; import com.red.circle.order.inner.model.dto.PayCountryDTO;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@ -68,6 +70,11 @@ public class SysPayCountryServiceImpl implements SysPayCountryService {
ResponseAssert.requiredSuccess(payCountryClient.shelf(id, shelf)); ResponseAssert.requiredSuccess(payCountryClient.shelf(id, shelf));
} }
@Override
public PayCountryCurrencyRateSyncDTO syncCurrencyRates(SysPayCountryCurrencyRateSyncCmd cmd) {
return ResponseAssert.requiredSuccess(payCountryClient.syncCurrencyRates(cmd));
}
@Override @Override
public Map<Long, PayCountryDTO> mapCountryByIds(Set<Long> ids) { public Map<Long, PayCountryDTO> mapCountryByIds(Set<Long> ids) {
return ResponseAssert.requiredSuccess(payCountryClient.mapCountryByIds(ids)); return ResponseAssert.requiredSuccess(payCountryClient.mapCountryByIds(ids));

View File

@ -2,7 +2,9 @@ package com.red.circle.console.app.service.app.sys.pay;
import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.dto.PageResult;
import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryCurrencyRateSyncCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd;
import com.red.circle.order.inner.model.dto.PayCountryCurrencyRateSyncDTO;
import com.red.circle.order.inner.model.dto.PayCountryDTO; import com.red.circle.order.inner.model.dto.PayCountryDTO;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
@ -59,6 +61,11 @@ public interface SysPayCountryService {
*/ */
void shelf(Long id, Boolean shelf); void shelf(Long id, Boolean shelf);
/**
* 同步支付国家默认货币和实时美元汇率.
*/
PayCountryCurrencyRateSyncDTO syncCurrencyRates(SysPayCountryCurrencyRateSyncCmd cmd);
/** /**
* 根据id集合获得. * 根据id集合获得.
*/ */

View File

@ -20,8 +20,13 @@ import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.http.RcHttpClient; import com.red.circle.tool.core.http.RcHttpClient;
import com.red.circle.tool.core.json.JacksonUtils; import com.red.circle.tool.core.json.JacksonUtils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -121,6 +126,27 @@ public class PayPlaceAnOrderService {
* @return 汇率值 * @return 汇率值
*/ */
public BigDecimal getRealTimeExchangeRate(String baseCurrency, String targetCurrency) { public BigDecimal getRealTimeExchangeRate(String baseCurrency, String targetCurrency) {
return getRealTimeExchangeRates(baseCurrency, List.of(targetCurrency)).get(targetCurrency);
}
public Map<String, BigDecimal> getRealTimeExchangeRates(String baseCurrency,
Collection<String> targetCurrencies) {
Map<String, BigDecimal> result = new HashMap<>();
Optional.ofNullable(targetCurrencies).orElseGet(List::of).stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(currency -> !currency.isEmpty())
.distinct()
.forEach(targetCurrency -> {
BigDecimal rate = queryRealTimeExchangeRate(baseCurrency, targetCurrency);
if (Objects.nonNull(rate)) {
result.put(targetCurrency, rate);
}
});
return result;
}
private BigDecimal queryRealTimeExchangeRate(String baseCurrency, String targetCurrency) {
try { try {
QuoteQueryParam param = new QuoteQueryParam(); QuoteQueryParam param = new QuoteQueryParam();
QuoteQueryParam.QuoteQueryData data = new QuoteQueryParam.QuoteQueryData(); QuoteQueryParam.QuoteQueryData data = new QuoteQueryParam.QuoteQueryData();

View File

@ -43,6 +43,8 @@ public interface PayCountryService extends BaseService<PayCountry> {
List<PayCountry> listOpenPayCountry(Set<Long> ids); List<PayCountry> listOpenPayCountry(Set<Long> ids);
List<PayCountry> listAllOpenPayCountry();
void delOpenPayCountry(List<Long> ids); void delOpenPayCountry(List<Long> ids);
void updateUsdExchangeRate(Long id, BigDecimal rate); void updateUsdExchangeRate(Long id, BigDecimal rate);
@ -52,4 +54,6 @@ public interface PayCountryService extends BaseService<PayCountry> {
void updateSort(Long id, Integer sort); void updateSort(Long id, Integer sort);
void shelf(Long id, Boolean shelf); void shelf(Long id, Boolean shelf);
boolean updateCurrencyRates(List<PayCountry> countries);
} }

View File

@ -17,6 +17,7 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
* <p> * <p>
@ -104,6 +105,13 @@ public class PayCountryServiceImpl extends BaseServiceImpl<PayCountryDAO, PayCou
.list(); .list();
} }
@Override
public List<PayCountry> listAllOpenPayCountry() {
return query()
.orderByDesc(PayCountry::getId)
.list();
}
@Override @Override
public void delOpenPayCountry(List<Long> ids) { public void delOpenPayCountry(List<Long> ids) {
delete() delete()
@ -147,4 +155,13 @@ public class PayCountryServiceImpl extends BaseServiceImpl<PayCountryDAO, PayCou
.execute(); .execute();
} }
@Override
@Transactional(rollbackFor = Exception.class)
public boolean updateCurrencyRates(List<PayCountry> countries) {
if (CollectionUtils.isEmpty(countries)) {
return Boolean.TRUE;
}
return updateBatchById(countries);
}
} }

View File

@ -6,7 +6,9 @@ import com.red.circle.order.inner.endpoint.api.PayCountryClientApi;
import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryCurrencyRateSyncCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd;
import com.red.circle.order.inner.model.dto.PayCountryCurrencyRateSyncDTO;
import com.red.circle.order.inner.model.dto.PayCountryDTO; import com.red.circle.order.inner.model.dto.PayCountryDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO;
@ -138,6 +140,12 @@ public class PayCountryClientEndpoint implements PayCountryClientApi {
return ResultResponse.success(); return ResultResponse.success();
} }
@Override
public ResultResponse<PayCountryCurrencyRateSyncDTO> syncCurrencyRates(
SysPayCountryCurrencyRateSyncCmd cmd) {
return ResultResponse.success(payCountryClientService.syncCurrencyRates(cmd));
}
@Override @Override
public ResultResponse<List<PayCountryDTO>> listPayCountryByRegionId(String regionId) { public ResultResponse<List<PayCountryDTO>> listPayCountryByRegionId(String regionId) {
return ResultResponse.success(payCountryClientService.listPayCountryByRegionId(regionId)); return ResultResponse.success(payCountryClientService.listPayCountryByRegionId(regionId));

View File

@ -4,7 +4,9 @@ import com.red.circle.framework.dto.PageResult;
import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryCurrencyRateSyncCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd;
import com.red.circle.order.inner.model.dto.PayCountryCurrencyRateSyncDTO;
import com.red.circle.order.inner.model.dto.PayCountryDTO; import com.red.circle.order.inner.model.dto.PayCountryDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO;
@ -57,5 +59,7 @@ public interface PayCountryClientService {
void shelf(Long id, Boolean shelf); void shelf(Long id, Boolean shelf);
PayCountryCurrencyRateSyncDTO syncCurrencyRates(SysPayCountryCurrencyRateSyncCmd cmd);
List<PayCountryDTO> listPayCountryByRegionId(String regionId); List<PayCountryDTO> listPayCountryByRegionId(String regionId);
} }

View File

@ -2,9 +2,11 @@ package com.red.circle.order.inner.service.impl;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists; import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.google.api.client.util.Maps; import com.google.api.client.util.Maps;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.framework.core.asserts.ResponseAssert; import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.constant.PageConstant; 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.PayCountry;
import com.red.circle.order.infra.database.rds.entity.pay.PayCountryChannel; import com.red.circle.order.infra.database.rds.entity.pay.PayCountryChannel;
import com.red.circle.order.infra.database.rds.entity.pay.PayCountryChannelDetails; import com.red.circle.order.infra.database.rds.entity.pay.PayCountryChannelDetails;
@ -15,7 +17,9 @@ import com.red.circle.order.inner.convertor.WebPayInnerConvertor;
import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryAddCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryChannelDetailsCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryCurrencyRateSyncCmd;
import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd; import com.red.circle.order.inner.model.cmd.SysPayCountryQryCmd;
import com.red.circle.order.inner.model.dto.PayCountryCurrencyRateSyncDTO;
import com.red.circle.order.inner.model.dto.PayCountryDTO; import com.red.circle.order.inner.model.dto.PayCountryDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDTO;
import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO; import com.red.circle.order.inner.model.dto.SysPayCountryChannelDetailsDTO;
@ -28,8 +32,14 @@ import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.other.inner.enums.user.RegionRelationGroupEnum; import com.red.circle.other.inner.enums.user.RegionRelationGroupEnum;
import com.red.circle.other.inner.endpoint.user.region.RegionRelationClient; import com.red.circle.other.inner.endpoint.user.region.RegionRelationClient;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -45,6 +55,11 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor @RequiredArgsConstructor
public class PayCountryClientServiceImpl implements PayCountryClientService { public class PayCountryClientServiceImpl implements PayCountryClientService {
private static final String BASE_CURRENCY = "USD";
private static final String SOURCE_NAME = "ISO4217/PayerMax";
private static final BigDecimal HUNDRED = BigDecimal.valueOf(100);
private static final int RATE_SCALE = 8;
private final PayCountryService payCountryService; private final PayCountryService payCountryService;
private final SysCountryCodeClient countryCodeClient; private final SysCountryCodeClient countryCodeClient;
private final WebPayInnerConvertor webPayInnerConvertor; private final WebPayInnerConvertor webPayInnerConvertor;
@ -52,6 +67,7 @@ public class PayCountryClientServiceImpl implements PayCountryClientService {
private final SysCountryCodeClient sysCountryCodeClient; private final SysCountryCodeClient sysCountryCodeClient;
private final PayCountryChannelService payCountryChannelService; private final PayCountryChannelService payCountryChannelService;
private final PayCountryChannelDetailsService payCountryChannelDetailsService; private final PayCountryChannelDetailsService payCountryChannelDetailsService;
private final PayPlaceAnOrderService payPlaceAnOrderService;
@Override @Override
@ -261,6 +277,105 @@ public class PayCountryClientServiceImpl implements PayCountryClientService {
payCountryService.shelf(id, shelf); payCountryService.shelf(id, shelf);
} }
@Override
public PayCountryCurrencyRateSyncDTO syncCurrencyRates(SysPayCountryCurrencyRateSyncCmd cmd) {
BigDecimal markupPercent = Optional.ofNullable(cmd)
.map(SysPayCountryCurrencyRateSyncCmd::getMarkupPercent)
.orElse(BigDecimal.ZERO);
BigDecimal markupMultiplier = BigDecimal.ONE.add(
markupPercent.divide(HUNDRED, RATE_SCALE, RoundingMode.HALF_UP));
List<PayCountry> payCountries = payCountryService.listAllOpenPayCountry();
if (CollectionUtils.isEmpty(payCountries)) {
return new PayCountryCurrencyRateSyncDTO()
.setTotalCount(0)
.setUpdatedCount(0)
.setSkippedCount(0)
.setSourceName(SOURCE_NAME)
.setSkippedCountries(Lists.newArrayList());
}
Map<Long, SysCountryCodeDTO> countryMap = ResponseAssert.requiredSuccess(
sysCountryCodeClient.mapByIdes(payCountries.stream()
.map(PayCountry::getCountryId)
.filter(Objects::nonNull)
.collect(Collectors.toSet())));
Map<Long, String> currencyMap = Maps.newHashMap();
List<String> skippedCountries = new ArrayList<>();
Set<String> targetCurrencies = payCountries.stream()
.map(payCountry -> {
SysCountryCodeDTO country = countryMap.get(payCountry.getCountryId());
String currency = resolveCountryCurrency(country);
if (StringUtils.isBlank(currency)) {
skippedCountries.add(formatSkippedCountry(payCountry, country, "未找到国家默认货币"));
return null;
}
currencyMap.put(payCountry.getId(), currency);
return currency;
})
.filter(StringUtils::isNotBlank)
.filter(currency -> !Objects.equals(BASE_CURRENCY, currency))
.collect(Collectors.toSet());
Map<String, BigDecimal> rateMap = Maps.newHashMap();
rateMap.put(BASE_CURRENCY, BigDecimal.ONE);
rateMap.putAll(payPlaceAnOrderService.getRealTimeExchangeRates(BASE_CURRENCY, targetCurrencies));
List<PayCountry> updates = payCountries.stream()
.map(payCountry -> buildSyncUpdate(payCountry, countryMap.get(payCountry.getCountryId()),
currencyMap.get(payCountry.getId()), rateMap, markupMultiplier, skippedCountries))
.filter(Objects::nonNull)
.collect(Collectors.toList());
ResponseAssert.isTrue(CommonErrorCode.OPERATING_FAILURE,
payCountryService.updateCurrencyRates(updates));
return new PayCountryCurrencyRateSyncDTO()
.setTotalCount(payCountries.size())
.setUpdatedCount(updates.size())
.setSkippedCount(skippedCountries.size())
.setSourceName(SOURCE_NAME)
.setSkippedCountries(skippedCountries);
}
private PayCountry buildSyncUpdate(PayCountry payCountry, SysCountryCodeDTO country,
String currency, Map<String, BigDecimal> rateMap, BigDecimal markupMultiplier,
List<String> skippedCountries) {
if (StringUtils.isBlank(currency)) {
return null;
}
BigDecimal rate = rateMap.get(currency);
if (Objects.isNull(rate) || rate.compareTo(BigDecimal.ZERO) <= 0) {
skippedCountries.add(formatSkippedCountry(payCountry, country, "未获取到实时汇率"));
return null;
}
payCountry.setCurrency(currency);
payCountry.setUsdExchangeRate(rate.multiply(markupMultiplier).setScale(RATE_SCALE,
RoundingMode.HALF_UP));
payCountry.setUpdateTime(TimestampUtils.now());
return payCountry;
}
private String resolveCountryCurrency(SysCountryCodeDTO country) {
if (Objects.isNull(country) || StringUtils.isBlank(country.getAlphaTwo())) {
return "";
}
try {
Locale locale = new Locale.Builder()
.setRegion(country.getAlphaTwo().trim().toUpperCase(Locale.ROOT))
.build();
return Currency.getInstance(locale).getCurrencyCode();
} catch (IllegalArgumentException | MissingResourceException e) {
return "";
}
}
private String formatSkippedCountry(PayCountry payCountry, SysCountryCodeDTO country,
String reason) {
String countryName = Optional.ofNullable(country)
.map(item -> StringUtils.isNotBlank(item.getAliasName()) ? item.getAliasName()
: item.getAlphaTwo())
.orElse(Objects.toString(payCountry.getCountryId(), "-"));
return countryName + "(" + payCountry.getId() + "): " + reason;
}
@Override @Override
public List<PayCountryDTO> listPayCountryByRegionId(String regionId) { public List<PayCountryDTO> listPayCountryByRegionId(String regionId) {