Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-03-06 16:00:52 +08:00
commit cec65bc424
35 files changed
+673 -132

No files matched your search

@@ -57,7 +57,7 @@ public class PermitAllUrlProperties implements InitializingBean {
*/
@Getter
@Setter
private boolean skipPublicUrl = false;
private boolean skipPublicUrl = true;
@Override
public void afterPropertiesSet() {
@@ -27,10 +27,14 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import java.util.Arrays;
import java.util.Objects;
/**
* @author pjcloud
* @date 2022-06-04
@@ -17,6 +17,7 @@ public enum HardOrderTypeEnum {
RESERVE("2", "线上订餐"),
FOREIGN_TICKET("3", "外来人员"),
STRIDE_DEPT("4", "跨单位"),
ZY("5", "正元公务餐"),
;
private final String type;
private final String description;
@@ -26,7 +27,7 @@ public enum HardOrderTypeEnum {
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
public static final List<HardOrderTypeEnum> refundList = List.of(BELOW, RESERVE);
public static final List<HardOrderTypeEnum> refundList = List.of(BELOW, RESERVE, FOREIGN_TICKET, ZY);
public static final List<HardOrderTypeEnum> payList = List.of(BELOW, RESERVE);
@@ -0,0 +1,25 @@
package com.bsd.pjcloud.hard.api.constant.third;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.hard.api.constant.HardPrintStatusEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
@AllArgsConstructor
@Getter
public enum HardCallbackPayStatus {
SUCCESS("0", "省平台认为流水交易完成,扣费成功"),
REPETITION("0001", "省平台则会每天定时重新发起扣费流程"),
ERROR("0002", "省平台则不再扣费,认为是坏账"),
NOT_SUFFICIENT_FUNDS("0003", "余额不足返回,省平台将会禁止该账户后续交易权限"),
;
private final String type;
private final String description;
public static HardCallbackPayStatus valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,16 @@
package com.bsd.pjcloud.hard.api.constant.third;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum HardCallbackRefundStatus {
SUCCESS("0", "省平台认为流水交易完成,扣费成功"),
REPETITION("0001", "省平台则会每天定时重新发起扣费流程"),
ERROR("0002", "省平台则不再扣费,认为是坏账"),
;
private final String type;
private final String description;
}
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.hard.api.dto.third;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class HardCallbackPayDto {
private Long userId;
private Integer payPrice;
private LocalDateTime payTime;
private String orderNo;
}
@@ -0,0 +1,15 @@
package com.bsd.pjcloud.hard.api.dto.third;
import lombok.Data;
@Data
public class HardCallbackRefundDto {
private Long orderId;
/**
* 智慧园区通刷服务平台冲正所产生的平台记录流水号
*/
private String serialNum;
}
@@ -31,6 +31,12 @@ public class HardOrderEntity extends Model<HardOrderEntity> {
@Schema(description="编号")
private Long id;
/**
* 订单编号
*/
@Schema(description="订单编号 目前正元正在使用")
private String orderNo;
/**
* 用户id
*/
@@ -1,19 +1,25 @@
package com.bsd.pjcloud.hard.api.feign;
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackPayDto;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackRefundDto;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackPayVo;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackRefundVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(contextId = "remoteHardThirdSelfZyService", value = ServiceNameConstants.HARDWARE_SERVICE)
public interface RemoteHardThirdSelfZyService {
@NoToken
@PostMapping("/hard-third-callback/pay")
void pay();
R<HardCallbackPayVo> pay(@RequestBody HardCallbackPayDto dto);
@NoToken
@PostMapping("/hard-third-callback/refund")
void refund();
R<HardCallbackRefundVo> refund(@RequestBody HardCallbackRefundDto dto);
}
@@ -0,0 +1,20 @@
package com.bsd.pjcloud.hard.api.vo.third;
import com.bsd.pjcloud.hard.api.constant.third.HardCallbackPayStatus;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class HardCallbackPayVo {
private Long orderId;
private LocalDateTime payTime;
private Long userId;
private String username;
private HardCallbackPayStatus code;
}
@@ -0,0 +1,32 @@
package com.bsd.pjcloud.hard.api.vo.third;
import com.bsd.pjcloud.hard.api.constant.third.HardCallbackRefundStatus;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class HardCallbackRefundVo {
private Long userId;
private String username;
/**
* 退款id
*/
private String refundId;
/**
* 订单编号
*/
private String orderNo;
/**
* 退款时间
*/
private LocalDateTime refundTime;
private HardCallbackRefundStatus code;
}
@@ -166,7 +166,7 @@ public class HardOrderController {
if (ObjectUtil.isNotEmpty(dto.getPayTimeList())) {
map.put("timeSpan", " 到 ");
map.put("startTime", LocalDateTimeUtil.format(dto.getPayTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getPayTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getPayTimeList()[1], DatePattern.NORM_DATETIME_PATTERN));
}
if (ObjectUtil.isNotEmpty(excelList)) {
BigDecimal totalPriceSum = BigDecimal.ZERO;
@@ -85,7 +85,7 @@ public class HardOrderTotalController {
if (ObjectUtil.isNotEmpty(dto.getPayTimeList())) {
map.put("timeSpan", " 到 ");
map.put("startTime", LocalDateTimeUtil.format(dto.getPayTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getPayTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getPayTimeList()[1], DatePattern.NORM_DATETIME_PATTERN));
}
if (ObjectUtil.isNotEmpty(list)) {
BigDecimal priceTotal = BigDecimal.ZERO;
@@ -128,7 +128,7 @@ public class HardOrderTotalController {
if (ObjectUtil.isNotEmpty(dto.getPayTimeList())) {
map.put("timeSpan", " 到 ");
map.put("startTime", LocalDateTimeUtil.format(dto.getPayTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getPayTimeList()[0], DatePattern.NORM_DATETIME_PATTERN));
map.put("endTime", LocalDateTimeUtil.format(dto.getPayTimeList()[1], DatePattern.NORM_DATETIME_PATTERN));
}
if (ObjectUtil.isNotEmpty(list)) {
BigDecimal priceTotal = BigDecimal.ZERO;
@@ -1,22 +1,19 @@
package com.bsd.pjcloud.hard.controller.third;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackPayDto;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackRefundDto;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackPayVo;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackRefundVo;
import com.bsd.pjcloud.hard.service.HardThirdSelfZyService;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
@@ -29,20 +26,20 @@ public class HardThirdSelfZyController {
/* ************************************* start 远程调用 start ************************************* */
@Inner(value = false)
@Inner
@PostMapping("/pay")
@SysLog("正元支付")
@Operation(summary = "正元支付")
public void pay() {
hardThirdSelfZyService.pay();
public R<HardCallbackPayVo> pay(@RequestBody HardCallbackPayDto dto) {
return R.ok(hardThirdSelfZyService.pay(dto));
}
@Inner(value = false)
@Inner
@PostMapping("/refund")
@SysLog("正元退款")
@Operation(summary = "正元退款")
public void refund() {
hardThirdSelfZyService.refund();
public R<HardCallbackRefundVo> refund(@RequestBody HardCallbackRefundDto dto) {
return R.ok(hardThirdSelfZyService.refund(dto));
}
/* ************************************* end 远程调用 end ************************************* */
@@ -9,6 +9,7 @@ import com.bsd.pjcloud.hard.api.dto.order.HardDisagreeDto;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleLogEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardAfterSaleVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import java.util.List;
@@ -51,6 +52,8 @@ public interface HardAfterSaleService extends IService<HardAfterSaleEntity> {
*/
void refund(Long afterSaleId);
void refund(Long afterSaleId, String prefixStr);
/**
* 同意售后
*
@@ -68,6 +71,11 @@ public interface HardAfterSaleService extends IService<HardAfterSaleEntity> {
*/
Boolean disagreeRefund(Long userId, HardDisagreeDto dto);
/**
* 校验订单是否可以退款
*/
HardOrderVo validateOrderCanRefund(Long orderId);
/**
* 后台退款
*
@@ -1,16 +1,20 @@
package com.bsd.pjcloud.hard.service;
import java.util.Map;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackPayDto;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackRefundDto;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackPayVo;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackRefundVo;
public interface HardThirdSelfZyService {
/**
* 正元支付
*/
void pay();
HardCallbackPayVo pay(HardCallbackPayDto dto);
/**
* 正元退款
*/
void refund();
HardCallbackRefundVo refund(HardCallbackRefundDto dto);
}
@@ -1,11 +1,42 @@
package com.bsd.pjcloud.hard.service.impl.hard;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.admin.api.dto.UserInfo;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
import com.bsd.pjcloud.hard.api.constant.refund.HardAfterSaleOperateTypeEnum;
import com.bsd.pjcloud.hard.api.constant.refund.HardSaleStatusEnum;
import com.bsd.pjcloud.hard.api.constant.refund.HardSaleTypeEnum;
import com.bsd.pjcloud.hard.api.constant.third.HardCallbackPayStatus;
import com.bsd.pjcloud.hard.api.constant.third.HardCallbackRefundStatus;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackPayDto;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackRefundDto;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleLogEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackPayVo;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackRefundVo;
import com.bsd.pjcloud.hard.mapper.order.HardAfterSaleLogMapper;
import com.bsd.pjcloud.hard.service.HardAfterSaleService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.hard.service.HardThirdSelfZyService;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
@Validated
@Slf4j
@@ -13,14 +44,131 @@ import org.springframework.validation.annotation.Validated;
@Service
public class HardThirdSelfZyServiceImpl implements HardThirdSelfZyService {
@Override
public void pay() {
private static final String TAG = "硬件正元回调";
private final RemoteWalletService remoteWalletService;
private final RemoteUserService remoteUserService;
private final HardOrderService hardOrderService;
private final HardAfterSaleLogMapper hardAfterSaleLogMapper;
private final HardAfterSaleService hardAfterSaleService;
/**
* 正元支付
*/
@Override
@Transactional(rollbackFor = Exception.class)
public HardCallbackPayVo pay(HardCallbackPayDto dto) {
try {
// 钱包
WalletManageEntity wallet = remoteWalletService.getWallet(dto.getUserId(), WalletTypeEnum.EAT).getData();
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("用户钱包不存在");
// 用户
UserInfo user = remoteUserService.getByUserId(wallet.getUserId()).getData();
if (ObjectUtil.isEmpty(user)) throw new RuntimeException("用户不存在");
Integer balance = wallet.getBalance();
int totalPrice = dto.getPayPrice();
if (balance < totalPrice) {
HardCallbackPayVo res = new HardCallbackPayVo();
res.setCode(HardCallbackPayStatus.NOT_SUFFICIENT_FUNDS);
return res;
}
String subject = "正元公务餐物品 * ?";
// 添加硬件订单
HardOrderEntity orderObj = HardOrderEntity.builder()
.orderNo(dto.getOrderNo())
.userId(dto.getUserId())
.parentCarId(null)
.sysType(null)
.orderStatus(HardOrderStatusEnum.CREATE.getType())
.merchantId(null)
.orderType(HardOrderTypeEnum.ZY.getType())
.payType(HardPayTypeEnum.WALLET_CARD.getType())
.orderSourceTypeId(null)
.totalPrice(totalPrice)
.extraPrice(0)
.payPrice(totalPrice)
.isOfflineOrder(YesNoEnum.NO.getCode())
.productDesc(subject)
.walletId(wallet.getId())
.build();
boolean isCreateOrder = hardOrderService.save(orderObj);
if (!isCreateOrder) throw new RuntimeException("创建订单失败");
hardOrderService.fastReduceBalance(orderObj);
HardCallbackPayVo result = new HardCallbackPayVo();
result.setCode(HardCallbackPayStatus.SUCCESS);
result.setOrderId(orderObj.getId());
result.setUserId(user.getSysUser().getUserId());
result.setUsername(user.getSysUser().getName());
result.setPayTime(LocalDateTime.now());
return result;
} catch (Exception e) {
log.error("|{}| pay 意外的错误dto:|{}|", TAG, JSONUtil.toJsonStr(dto), e);
HardCallbackPayVo result = new HardCallbackPayVo();
result.setCode(HardCallbackPayStatus.REPETITION);
return result;
}
}
/**
* 正元退款
*/
@Override
public void refund() {
@Transactional(rollbackFor = Exception.class)
public HardCallbackRefundVo refund(HardCallbackRefundDto dto) {
try {
// 校验订单是否可以退款
HardOrderVo order = hardAfterSaleService.validateOrderCanRefund(dto.getOrderId());
if (!ObjectUtil.equals(dto.getSerialNum(), order.getOrderNo())) {
throw new RuntimeException("正元订单号不匹配");
}
// 用户
UserInfo user = remoteUserService.getByUserId(order.getUserId()).getData();
if (ObjectUtil.isEmpty(user)) throw new RuntimeException("用户不存在");
// 添加售后订单
HardAfterSaleEntity saveObj = BeanUtils.toBean(dto, HardAfterSaleEntity.class);
String refundCode = "zy_" + order.getId();
saveObj.setType(HardSaleTypeEnum.AFTER_SALE.getType());
saveObj.setStatus(HardSaleStatusEnum.COMPLETE.getStatus());
saveObj.setNo(refundCode);
saveObj.setWay("10");
saveObj.setOrderId(order.getId());
saveObj.setRefundPrice(order.getPayPrice());
saveObj.setUserId(order.getUserId());
saveObj.setAuditUserId(null);
saveObj.setAuditTime(LocalDateTime.now());
saveObj.setApplyReason("正元api退款");
saveObj.setAuditReason("正元api退款");
saveObj.setApplyDescription("正元api退款");
hardAfterSaleService.save(saveObj);
// 添加售后进度
HardAfterSaleLogEntity saveLogObj = HardAfterSaleLogEntity.builder()
.afterSaleId(saveObj.getId())
.userId(order.getUserId())
.operateType(HardAfterSaleOperateTypeEnum.ADMIN_REFUND.getType())
.beforeStatus(order.getOrderStatus())
.afterStatus(HardSaleStatusEnum.COMPLETE.getStatus())
.content(HardSaleStatusEnum.COMPLETE.getContent())
.build();
hardAfterSaleLogMapper.insert(saveLogObj);
// 执行退款
hardAfterSaleService.refund(saveObj.getId(),"zy");
// 退库存
hardOrderService.fastenerInventory(order, YesNoEnum.NO);
HardCallbackRefundVo result = new HardCallbackRefundVo();
result.setCode(HardCallbackRefundStatus.SUCCESS);
result.setRefundId(String.valueOf(saveObj.getId()));
result.setOrderNo(order.getOrderNo());
result.setUserId(user.getSysUser().getUserId());
result.setUsername(user.getSysUser().getName());
result.setRefundTime(LocalDateTime.now());
return result;
} catch (Exception e) {
log.error("|{}| pay 意外的错误dto:|{}|", TAG, JSONUtil.toJsonStr(dto), e);
HardCallbackRefundVo result = new HardCallbackRefundVo();
result.setCode(HardCallbackRefundStatus.REPETITION);
return result;
}
}
}
@@ -209,12 +209,19 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
@Override
@Transactional(rollbackFor = Exception.class)
public void refund(Long afterSaleId) {
getSelf().refund(afterSaleId, null);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void refund(Long afterSaleId, String prefixStr) {
HardAfterSaleEntity afterSale = baseMapper.selectById(afterSaleId);
if (ObjectUtil.isEmpty(afterSale)) throw new RuntimeException("售后订单不存在");
// 校验订单是否可以退款
HardOrderVo order = validateOrderCanRefund(afterSale.getOrderId());
// 生成退款单号
String refundCode = "hard_" + order.getId();
if (ObjectUtil.isEmpty(prefixStr)) prefixStr = "hard";
String refundCode = prefixStr + "_" + order.getId();
// 创建退款单
WalletRechargeRefundDto hardRefundDto = WalletRechargeRefundDto.builder().walletId(order.getWalletId()).orderId(order.getId()).afterSaleId(afterSale.getId()).refundCode(refundCode).reason("订单退款").price(order.getPayPrice()).build();
R<WalletRechargeVo> walletRefundResult = walletRechargeService.refund(hardRefundDto);
@@ -297,7 +304,7 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
}
// 校验订单是否可以退款
private HardOrderVo validateOrderCanRefund(Long orderId) {
public HardOrderVo validateOrderCanRefund(Long orderId) {
HardOrderEntity order = hardOrderService.getById(orderId);
if (ObjectUtil.isEmpty(order)) throw new RuntimeException("订单不存在");
HardOrderVo orderVo = BeanUtils.toBean(order, HardOrderVo.class);
@@ -351,8 +351,10 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
HardOrderEntity update = HardOrderEntity.builder().id(order.getId()).payTime(LocalDateTime.now()).orderStatus(HardOrderStatusEnum.PAY.getType()).payPrice(payPrice).build();
baseMapper.updateById(update);
// 父购物车订单表订单状态
HardParentCarEntity updateParentCar = HardParentCarEntity.builder().id(order.getParentCarId()).orderStatus(HardOrderStatusEnum.PAY.getType()).build();
hardParentCarServiceImpl.updateById(updateParentCar);
if (ObjectUtil.isNotEmpty(order.getParentCarId())) {
HardParentCarEntity updateParentCar = HardParentCarEntity.builder().id(order.getParentCarId()).orderStatus(HardOrderStatusEnum.PAY.getType()).build();
hardParentCarServiceImpl.updateById(updateParentCar);
}
}
}
@@ -4,6 +4,7 @@
<mapper namespace="com.bsd.pjcloud.hard.mapper.order.HardOrderMapper">
<resultMap id="hardwareOrderMap" type="com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity">
<id property="id" column="id"/>
<result property="orderNo" column="order_no"/>
<result property="userId" column="user_id"/>
<result property="merchantId" column="merchant_id"/>
<result property="hardId" column="hard_id"/>
@@ -39,6 +40,7 @@
<sql id="selectA">
select a.id,
a.order_no,
a.user_id,
a.merchant_id,
a.hard_id,
@@ -194,13 +196,19 @@
COALESCE(COUNT(0), 0) AS totalNum,
COALESCE(SUM(a.pay_price), 0) AS totalMoney,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) THEN 1 ELSE 0 END), 0) AS totalNumYear,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) THEN a.pay_price ELSE 0 END), 0) AS totalMoneyYear,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) THEN 1 ELSE 0 END), 0) AS totalNumMonth,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) THEN a.pay_price ELSE 0 END), 0) AS totalMoneyMonth,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) AND DAY(a.create_time) = DAY(CURRENT_DATE()) THEN 1 ELSE 0 END), 0) AS totalNumDay,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) = MONTH(CURRENT_DATE()) AND DAY(a.create_time) = DAY(CURRENT_DATE()) THEN a.pay_price ELSE 0 END), 0) AS totalMoneyDay
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) THEN a.pay_price ELSE 0 END), 0) AS
totalMoneyYear,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) =
MONTH(CURRENT_DATE()) THEN 1 ELSE 0 END), 0) AS totalNumMonth,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) =
MONTH(CURRENT_DATE()) THEN a.pay_price ELSE 0 END), 0) AS totalMoneyMonth,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) =
MONTH(CURRENT_DATE()) AND DAY(a.create_time) = DAY(CURRENT_DATE()) THEN 1 ELSE 0 END), 0) AS totalNumDay,
COALESCE(SUM(CASE WHEN YEAR(a.create_time) = YEAR(CURRENT_DATE()) AND MONTH(a.create_time) =
MONTH(CURRENT_DATE()) AND DAY(a.create_time) = DAY(CURRENT_DATE()) THEN a.pay_price ELSE 0 END), 0) AS
totalMoneyDay
FROM
hard_order a
hard_order a
<where>
a.del_flag = 0
<if test="dto.orderStatusCodes != null and dto.orderStatusCodes.size() != 0">
@@ -1,10 +1,10 @@
package com.bsd.pjcloud.thirdparty.vo.zy;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
public class ZyBaseVo {
@@ -54,4 +54,9 @@ public class ZyBaseVo {
return ObjectUtil.equal(code, ZyBaseVo.successCode);
}
@JsonIgnore
public Map<String, Object> getErrorMap() {
return Map.of("code", code, "msg", msg);
}
}
@@ -41,6 +41,7 @@ public class ThirdZyLogController {
@PreAuthorize("@pms.hasPermission('third_thirdZyLog_view')")
public R getThirdZyLogPage(@ParameterObject Page page, @ParameterObject ThirdZyLogEntity thirdZyLog) {
LambdaQueryWrapper<ThirdZyLogEntity> wrapper = Wrappers.lambdaQuery();
wrapper.orderByDesc(ThirdZyLogEntity::getCreateTime);
return R.ok(thirdZyLogService.page(page, wrapper));
}
@@ -27,7 +27,7 @@ public class ThirdZySelfController {
@Inner(value = false)
@GetMapping("/checkSystemStatus")
@Operation(summary = "第三方url健康探测", description = "第三方url健康探测")
@Idempotent(expireTime = 10, info = "请勿重复调用")
@Idempotent(expireTime = 3, info = "请勿重复调用")
public Map<String, Object> checkSystemStatus() {
return zySelfService.checkSystemStatus();
}
@@ -35,7 +35,7 @@ public class ThirdZySelfController {
@Inner(value = false)
@GetMapping("/getToken")
@Operation(summary = "第三方提供获取token", description = "第三方提供获取token")
@Idempotent(expireTime = 10, info = "请勿重复调用")
@Idempotent(expireTime = 3, info = "请勿重复调用")
public ZySelfGetTokenVo getToken(ZySelfGetTokenDto params) {
return zySelfService.getToken(params);
}
@@ -43,15 +43,14 @@ public class ThirdZySelfController {
@Inner(value = false)
@PostMapping("/correct")
@Operation(summary = "第三方一卡通系统提供冲正接口", description = "第三方一卡通系统提供冲正接口")
public ZySelfCorrectVo correct(ZySelfCorrectDto params, @RequestParam(value = "access_token", required = false) String accessToken) {
public Map<String, Object> correct(ZySelfCorrectDto params, @RequestParam(value = "access_token", required = false) String accessToken) {
return zySelfService.correct(params, accessToken);
}
@Inner(value = false)
@PostMapping("/pay")
@Operation(summary = "第三方一卡通系统提供扣费接口", description = "第三方一卡通系统提供扣费接口")
@Idempotent(expireTime = 10, info = "请勿重复调用")
public ZySelfPayVo pay(ZySelfPayDto params, @RequestParam(value = "access_token", required = false) String accessToken) {
public Map<String, Object> pay(ZySelfPayDto params, @RequestParam(value = "access_token", required = false) String accessToken) {
return zySelfService.pay(params, accessToken);
}
@@ -20,6 +20,14 @@ public interface ThirdZyIdDictMapper extends PjcloudBaseMapper<ThirdZyIdDictEnti
return selectList(wrapper);
}
default ThirdZyIdDictEntity getBySelfId(ThirdZyBizEnumType type, String selfId) {
if (ObjectUtil.isEmpty(type)) return null;
LambdaQueryWrapper<ThirdZyIdDictEntity> wrapper = new LambdaQueryWrapper<ThirdZyIdDictEntity>()
.eq(ObjectUtil.isNotEmpty(selfId), ThirdZyIdDictEntity::getSelfId, selfId)
.eq(ThirdZyIdDictEntity::getBizType, type.getType());
return selectOne(wrapper);
}
default List<ThirdZyIdDictEntity> getByZyIds(ThirdZyBizEnumType type, List<String> zyIds) {
if (ObjectUtil.isEmpty(type)) return null;
LambdaQueryWrapper<ThirdZyIdDictEntity> wrapper = new LambdaQueryWrapper<ThirdZyIdDictEntity>()
@@ -28,4 +36,12 @@ public interface ThirdZyIdDictMapper extends PjcloudBaseMapper<ThirdZyIdDictEnti
return selectList(wrapper);
}
default ThirdZyIdDictEntity getByZyIds(ThirdZyBizEnumType type, String zyId) {
if (ObjectUtil.isEmpty(type)) return null;
LambdaQueryWrapper<ThirdZyIdDictEntity> wrapper = new LambdaQueryWrapper<ThirdZyIdDictEntity>()
.eq(ObjectUtil.isNotEmpty(zyId), ThirdZyIdDictEntity::getZyId, zyId)
.eq(ThirdZyIdDictEntity::getBizType, type.getType());
return selectOne(wrapper);
}
}
@@ -24,10 +24,10 @@ public interface ThirdZySelfService {
/**
* 第三方一卡通系统提供冲正接口
*/
ZySelfCorrectVo correct(ZySelfCorrectDto params, String accessToken);
Map<String, Object> correct(ZySelfCorrectDto params, String accessToken);
/**
* 第三方一卡通系统提供扣费接口
*/
ZySelfPayVo pay(ZySelfPayDto params, String accessToken);
Map<String, Object> pay(ZySelfPayDto params, String accessToken);
}
@@ -23,9 +23,7 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Service
@Validated
@@ -66,7 +64,7 @@ public class ThirdZyForeignServiceImpl implements ThirdZyForeignService {
Map<String, Object> encryptionBody = BeanUtil.beanToMap(dto);
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody);
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody);
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -55,21 +55,18 @@ public class ThirdZyMerServiceImpl implements ThirdZyMerService {
// 转换商户id
List<String> mchList = dto.stream().map(ZyMerSyncDealerInfoDto::getDealerKeyObj).distinct().toList();
Map<String, String> mchIdDict = zyApiTool.generateZyId(bizTYpe, mchList);
List<Map<String, Object>> listMap = new ArrayList<>();
for (ZyMerSyncDealerInfoDto v : dto) {
v.setEPID(deptDdDict.get(v.getEPID()));
v.setDealerKeyObj(mchIdDict.get(v.getDealerKeyObj()));
Map<String, Object> map = zyApiTool.removeEmptyMap(BeanUtil.beanToMap(v));
if (ObjectUtil.isNotEmpty(map)) listMap.add(map);
}
String url = zyConfig.getBaseUrl() + ZyApi.Mer.SYNC_DEALER_INFO;
try {
url = String.format(url, zyApiTool.getToken());
Map<String, Object> encryptionBody = new HashMap<>();
encryptionBody.put("dealers", listMap);
encryptionBody.put("dealers", dto);
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody);
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody);
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -103,23 +100,20 @@ public class ThirdZyMerServiceImpl implements ThirdZyMerService {
ThirdZyLogEntity entity = new ThirdZyLogEntity();
entity.setBizType(bizType.getType());
long startTime = System.currentTimeMillis();
List<Map<String, Object>> listMap = new ArrayList<>();
// 转换zyId
List<String> list = dto.stream().map(ZyMerSyncEnterpriseInfoDto::getEPID).distinct().toList();
Map<String, String> idDict = zyApiTool.generateZyId(bizType, list);
for (ZyMerSyncEnterpriseInfoDto v : dto) {
v.setEPID(idDict.get(v.getEPID()));
Map<String, Object> map = zyApiTool.removeEmptyMap(BeanUtil.beanToMap(v));
if (ObjectUtil.isNotEmpty(map)) listMap.add(map);
}
String url = zyConfig.getBaseUrl() + ZyApi.Mer.SYNC_ENTERPRISE_INFO;
try {
url = String.format(url, zyApiTool.getToken());
Map<String, Object> encryptionBody = new HashMap<>();
encryptionBody.put("enterprises", listMap);
encryptionBody.put("enterprises", dto);
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody);
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody);
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -164,6 +158,7 @@ public class ThirdZyMerServiceImpl implements ThirdZyMerService {
Map<String, String> roleIdDict = zyApiTool.generateZyId(bizType, roleList);
for (ZyMerSyncAccountInfoDto v : dto) {
v.setEPID(deptIdDict.get(v.getEPID()));
v.setPerCode(userIdDict.get(v.getPerCode()));
v.setAccNum(userIdDict.get(v.getAccNum()));
v.setAccClassID(roleIdDict.get(v.getAccClassID()));
}
@@ -179,7 +174,7 @@ public class ThirdZyMerServiceImpl implements ThirdZyMerService {
encryptionBody.put("currentMaxFixId", String.valueOf(maxFixId.getAsLong()));
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody, "data", "currentMaxFixId");
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody, "data", "currentMaxFixId");
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -219,21 +214,18 @@ public class ThirdZyMerServiceImpl implements ThirdZyMerService {
long startTime = System.currentTimeMillis();
String url = zyConfig.getBaseUrl() + ZyApi.Mer.SYNC_ACC_CLASS_INFO;
try {
List<Map<String, Object>> listMap = new ArrayList<>();
// 转换zyId
List<String> roleList = dto.stream().map(ZyMerSyncAccClassInfoDto::getEPID).distinct().toList();
Map<String, String> roleIdDict = zyApiTool.generateZyId(bizType, roleList);
for (ZyMerSyncAccClassInfoDto v : dto) {
v.setEPID(roleIdDict.get(v.getEPID()));
Map<String, Object> map = zyApiTool.removeEmptyMap(BeanUtil.beanToMap(v));
if (ObjectUtil.isNotEmpty(map)) listMap.add(map);
}
url = String.format(url, zyApiTool.getToken());
Map<String, Object> encryptionBody = new HashMap<>();
encryptionBody.put("accClasses", listMap);
encryptionBody.put("accClasses", dto);
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody);
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody);
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -1,21 +1,35 @@
package com.bsd.pjcloud.thirdparty.service.impl.zy;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.hard.api.constant.third.HardCallbackRefundStatus;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackPayDto;
import com.bsd.pjcloud.hard.api.dto.third.HardCallbackRefundDto;
import com.bsd.pjcloud.hard.api.feign.RemoteHardThirdSelfZyService;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackPayVo;
import com.bsd.pjcloud.hard.api.vo.third.HardCallbackRefundVo;
import com.bsd.pjcloud.thirdparty.config.ZyConfig;
import com.bsd.pjcloud.thirdparty.constant.ThirdZyBizEnumType;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfCorrectDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfGetTokenDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfPayDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfTokenDto;
import com.bsd.pjcloud.thirdparty.entity.zy.ThirdZyIdDictEntity;
import com.bsd.pjcloud.thirdparty.entity.zy.ThirdZyLogEntity;
import com.bsd.pjcloud.thirdparty.mapper.zy.ThirdZyIdDictMapper;
import com.bsd.pjcloud.thirdparty.service.impl.ThirdZySelfService;
import com.bsd.pjcloud.thirdparty.utils.zy.api.ZyApi;
import com.bsd.pjcloud.thirdparty.utils.zy.api.ZyApiTool;
import com.bsd.pjcloud.thirdparty.vo.zy.ZyBaseVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfCorrectVo;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfGetTokenVo;
@@ -29,6 +43,8 @@ import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -45,9 +61,12 @@ public class ThirdZySelfServiceImpl implements ThirdZySelfService {
private final StringRedisTemplate redisTemplate;
private final ThirdZyLogServiceImpl thirdZyLogService;
private final ThirdZyIdDictMapper thirdZyIdDictMapper;
private final RemoteHardThirdSelfZyService hardCallback;
private final ZyApiTool zyApiTool;
/**
* 第三方url健康探测
*/
@@ -79,13 +98,14 @@ public class ThirdZySelfServiceImpl implements ThirdZySelfService {
* 第三方一卡通系统提供冲正接口
*/
@Override
public ZySelfCorrectVo correct(ZySelfCorrectDto params, String accessToken) {
public Map<String, Object> correct(ZySelfCorrectDto params, String accessToken) {
ThirdZyBizEnumType bizType = ThirdZyBizEnumType.SELF_CORRECT;
ThirdZyLogEntity entity = new ThirdZyLogEntity();
entity.setBizType(bizType.getType());
entity.setApiUrl(ZyApi.Self.CORRECT);
long startTime = System.currentTimeMillis();
ZySelfCorrectVo result = new ZySelfCorrectVo();
try {
ZySelfCorrectVo result = new ZySelfCorrectVo();
result.setCode(ZyBaseVo.errorCode);
boolean isToken = checkIsToken(accessToken);
// 判断token
@@ -96,19 +116,50 @@ public class ThirdZySelfServiceImpl implements ThirdZySelfService {
throw new RuntimeException(msg);
}
// 校验加密参数
boolean isSign = checkSign(params);
if (!isSign) {
String jsonRes = checkSign(params);
if (ObjectUtil.isEmpty(jsonRes)) {
String msg = "数据加密认证失败!sign值验证失败";
result.setCode(ZyBaseVo.signError);
result.setMsg(msg);
throw new RuntimeException(msg);
}
return null;
result.setCode(ZyBaseVo.errorCode);
result.setMsg(ZyBaseVo.defaultErrorMsg);
ZySelfCorrectDto dto = JSONUtil.toBean(jsonRes, ZySelfCorrectDto.class);
entity.setEncipherReq(JSONUtil.toJsonStr(dto));
// 获取参数
String correctSerialNum = dto.getCorrectSerialNum();
Long orderId = Long.parseLong(correctSerialNum);
// 调用硬件接口
HardCallbackRefundDto refundDto = new HardCallbackRefundDto();
refundDto.setOrderId(orderId);
refundDto.setSerialNum(dto.getSerialNum());
HardCallbackRefundVo refundRes = hardCallback.refund(refundDto).getData();
result.setCode(refundRes.getCode().getType());
switch (refundRes.getCode()) {
case SUCCESS -> {
ThirdZyIdDictEntity userIdDict = thirdZyIdDictMapper.getBySelfId(ThirdZyBizEnumType.SYNC_ACCOUNT_INFO, String.valueOf(refundRes.getUserId()));
String userZyId = userIdDict.getZyId();
result.setAccNum(userZyId);
result.setAccName(refundRes.getUsername());
result.setPerCode(userZyId);
result.setPlatformSerialNum(String.valueOf(refundRes.getRefundId()));
result.setSerialNum(refundRes.getOrderNo());
result.setRecDate(LocalDateTimeUtil.format(refundRes.getRefundTime(), DatePattern.NORM_DATETIME_PATTERN));
result.setAmount(dto.getAmount());
result.setMsg(ZyBaseVo.selfSuccessMsg);
entity.setOrgReq(JSONUtil.toJsonStr(result));
Map<String, Object> encryptionRes = zyApiTool.getSelfEncryptionMap(BeanUtil.beanToMap(result));
entity.setEncipherReq(JSONUtil.toJsonStr(encryptionRes));
return encryptionRes;
}
default -> throw new RuntimeException();
}
} catch (Exception e) {
String error = String.format("|%s||correct|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
entity.setError(error);
return null;
return result.getErrorMap();
} finally {
long elapsedTime = System.currentTimeMillis() - startTime;
entity.setTimeConsuming(Long.toString(elapsedTime));
@@ -120,10 +171,12 @@ public class ThirdZySelfServiceImpl implements ThirdZySelfService {
* 第三方一卡通系统提供扣费接口
*/
@Override
public ZySelfPayVo pay(ZySelfPayDto params, String accessToken) {
public Map<String, Object> pay(ZySelfPayDto params, String accessToken) {
ThirdZyBizEnumType bizType = ThirdZyBizEnumType.SELF_PAY;
ThirdZyLogEntity entity = new ThirdZyLogEntity();
entity.setApiUrl(ZyApi.Self.PAY);
entity.setBizType(bizType.getType());
entity.setEncipherReq(JSONUtil.toJsonStr(params));
long startTime = System.currentTimeMillis();
ZySelfPayVo result = new ZySelfPayVo();
try {
@@ -137,19 +190,60 @@ public class ThirdZySelfServiceImpl implements ThirdZySelfService {
throw new RuntimeException(msg);
}
// 校验加密参数
boolean isSign = checkSign(params);
if (!isSign) {
String jsonRes = checkSign(params);
if (ObjectUtil.isEmpty(jsonRes)) {
String msg = "数据加密认证失败!sign值验证失败";
result.setCode(ZyBaseVo.signError);
result.setMsg(msg);
throw new RuntimeException(msg);
}
return result;
result.setCode(ZyBaseVo.errorCode);
result.setMsg(ZyBaseVo.defaultErrorMsg);
ZySelfPayDto dto = JSONUtil.toBean(jsonRes, ZySelfPayDto.class);
entity.setEncipherReq(JSONUtil.toJsonStr(dto));
// 获取参数
String accNum = dto.getAccNum();
ThirdZyIdDictEntity userIdDict = thirdZyIdDictMapper.getByZyIds(ThirdZyBizEnumType.SYNC_ACCOUNT_INFO, accNum);
if (ObjectUtil.isEmpty(userIdDict)) {
throw new RuntimeException("用户id不存在");
}
String amount = dto.getAmount();
if (ObjectUtil.isEmpty(amount)) {
throw new RuntimeException("金额转换失败");
}
int payPrice = new BigDecimal(amount).multiply(BigDecimal.valueOf(100)).intValue();
String dealTime = dto.getDealTime();
LocalDateTime payTime = LocalDateTimeUtil.parse(dealTime, DatePattern.NORM_DATETIME_PATTERN);
// 调用硬件接口
HardCallbackPayDto payDto = new HardCallbackPayDto();
payDto.setUserId(Long.valueOf(userIdDict.getSelfId()));
payDto.setPayPrice(payPrice);
payDto.setPayTime(payTime);
payDto.setOrderNo(dto.getSerialNum());
HardCallbackPayVo payRes = hardCallback.pay(payDto).getData();
result.setCode(payRes.getCode().getType());
switch (payRes.getCode()) {
case SUCCESS -> {
result.setAccNum(payRes.getUserId().toString());
result.setAccName(payRes.getUsername());
result.setPerCode(payRes.getUserId().toString());
result.setPlatformSerialNum(dto.getSerialNum());
result.setSerialNum(dto.getSerialNum());
result.setAmount(amount);
result.setRecDate(LocalDateTimeUtil.format(payRes.getPayTime(), DatePattern.NORM_DATETIME_PATTERN));
result.setMsg(ZyBaseVo.selfSuccessMsg);
entity.setOrgReq(JSONUtil.toJsonStr(result));
Map<String, Object> encryptionRes = zyApiTool.getSelfEncryptionMap(BeanUtil.beanToMap(result));
entity.setEncipherReq(JSONUtil.toJsonStr(encryptionRes));
return encryptionRes;
}
default -> throw new RuntimeException();
}
} catch (Exception e) {
String error = String.format("|%s||pay|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
entity.setError(error);
return result;
return result.getErrorMap();
} finally {
long elapsedTime = System.currentTimeMillis() - startTime;
entity.setTimeConsuming(Long.toString(elapsedTime));
@@ -210,46 +304,68 @@ public class ThirdZySelfServiceImpl implements ThirdZySelfService {
log.info("|{}|checkIsToken校验错误,未传入token|{}|", TAG, string);
return false;
}
Claims claims = Jwts.parser()
.setSigningKey(zyConfig.getSelfAppSecret())
.parseClaimsJws(string)
.getBody();
String token = (String) claims.get(zyConfig.getSelfTokenKey());
String redisKey = CacheConstants.THIRDPARTY_ZY_SELF_TOKEN + token;
String json = redisTemplate.opsForValue().get(redisKey);
if (ObjectUtil.isEmpty(json)) {
log.info("|{}|checkIsToken校验错误token|{}|", TAG, string);
try {
Claims claims = Jwts.parser()
.setSigningKey(zyConfig.getSelfTokenSecret())
.parseClaimsJws(string)
.getBody();
String token = (String) claims.get(zyConfig.getSelfTokenKey());
String redisKey = CacheConstants.THIRDPARTY_ZY_SELF_TOKEN + token;
String json = redisTemplate.opsForValue().get(redisKey);
if (ObjectUtil.isEmpty(json)) {
log.error("|{}|checkIsToken校验错误token|{}|", TAG, string);
return false;
}
log.info("|{}|checkIsToken校验成功info|{}|", TAG, json);
return true;
} catch (Exception e) {
log.error("|{}|checkIsToken意外的错误token|{}|", TAG, string);
return false;
}
log.info("|{}|checkIsToken校验成功info|{}|", TAG, json);
return true;
}
/**
* 校验参数
*/
private boolean checkSign(Object obj) {
if (ObjectUtil.isEmpty(obj)) return false;
private String checkSign(Object obj) {
if (ObjectUtil.isEmpty(obj)) return null;
try {
Map<String, Object> map = BeanUtil.beanToMap(obj);
if (ObjectUtil.isEmpty(map)) return false;
if (ObjectUtil.isEmpty(map)) return null;
Map<String, Object> paramsMap = new TreeMap<>(map);
paramsMap.remove("sign");
String sign = map.getOrDefault("sign", "").toString();
if (ObjectUtil.isEmpty(sign)) {
log.error("|{}|checkSign意外的错误,sign为空", sign);
return false;
return null;
}
if (ObjectUtil.isEmpty(paramsMap)) {
log.error("|{}|checkSign意外的错误,paramsMap为空", paramsMap);
return false;
return null;
}
for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
entry.setValue(Base64.decodeStr((String) value));
} else {
entry.setValue(Base64.decodeStr(value.toString()));
}
}
String string = zyApiTool.generateSign(paramsMap, false);
if (ObjectUtil.equals(sign, string)) {
for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
entry.setValue(URLUtil.decode((String) value));
}
}
return JSONUtil.toJsonStr(paramsMap);
}
return true;
} catch (Exception e) {
log.error("|{}|checkSign意外的错误,加密参数|{}|", TAG, JSONUtil.toJsonStr(obj), e);
return false;
return null;
}
return null;
}
// 生成token
@@ -51,7 +51,7 @@ public class ThirdZyStrideServiceImpl implements ThirdZyStrideService {
encryptionBody.put("dealers", dto);
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody);
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody);
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -90,7 +90,7 @@ public class ThirdZyStrideServiceImpl implements ThirdZyStrideService {
encryptionBody.put("dealers", dto);
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody);
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody);
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -129,7 +129,7 @@ public class ThirdZyStrideServiceImpl implements ThirdZyStrideService {
encryptionBody.put("dealers", dto);
entity.setApiUrl(url);
entity.setOrgReq(JSONUtil.toJsonStr(encryptionBody));
Map<String, Object> body = zyApiTool.getEncryptionMap(encryptionBody);
Map<String, Object> body = zyApiTool.getZyEncryptionMap(encryptionBody);
entity.setEncipherReq(JSONUtil.toJsonStr(body));
String res = HttpRequest.post(url).form(body).execute().body();
if (ObjectUtil.isEmpty(res)) {
@@ -6,15 +6,12 @@ import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.thirdparty.config.ZyConfig;
import com.bsd.pjcloud.thirdparty.constant.ThirdZyBizEnumType;
import com.bsd.pjcloud.thirdparty.entity.zy.ThirdZyIdDictEntity;
import com.bsd.pjcloud.thirdparty.mapper.zy.ThirdZyIdDictMapper;
import com.bsd.pjcloud.thirdparty.vo.zy.mer.ZyMerGetTokenVo;
import io.undertow.security.idm.DigestAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -23,8 +20,6 @@ import org.springframework.validation.annotation.Validated;
import org.apache.commons.codec.digest.DigestUtils;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -135,35 +130,47 @@ public class ZyApiTool {
return result;
}
public Map<String, Object> getEncryptionMap(Map<String, Object> params, String... str) {
/**
* 获取正元传输的数据
*/
public Map<String, Object> getZyEncryptionMap(Map<String, Object> params, String... str) {
Map<String, Object> body = new LinkedHashMap<>();
if (ObjectUtil.isEmpty(str)) return body;
for (String v : str) {
body.put(v, params.getOrDefault(v, null));
}
prePost(body);
prePost(body, true);
return body;
}
public Map<String, Object> getEncryptionMap(Map<String, Object> params) {
public Map<String, Object> getZyEncryptionMap(Map<String, Object> params) {
Map<String, Object> body = new HashMap<>();
body.put("data", params);
prePost(body);
prePost(body, true);
return body;
}
public Map<String, Object> removeEmptyMap(Map<String, Object> params) {
if (ObjectUtil.isEmpty(params)) return null;
for (Map.Entry<String, Object> entry : params.entrySet()) {
Object value = entry.getValue();
if (value == null) {
params.remove(entry.getKey());
}
/**
* 获取第三方传输的数据
*/
public Map<String, Object> getSelfEncryptionMap(Map<String, Object> params, String... str) {
Map<String, Object> body = new LinkedHashMap<>();
if (ObjectUtil.isEmpty(str)) return body;
for (String v : str) {
body.put(v, params.getOrDefault(v, null));
}
return params;
prePost(body, false);
return body;
}
private void prePost(Map<String, Object> params) {
public Map<String, Object> getSelfEncryptionMap(Map<String, Object> params) {
Map<String, Object> body = new HashMap<>();
body.put("data", params);
prePost(body, false);
return body;
}
private void prePost(Map<String, Object> params, boolean isZy) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
@@ -173,7 +180,7 @@ public class ZyApiTool {
entry.setValue(json);
}
}
String sign = generateSign(params);
String sign = generateSign(params, isZy);
for (Map.Entry<String, Object> entry : params.entrySet()) {
Object value = entry.getValue();
if (value instanceof String) {
@@ -185,7 +192,7 @@ public class ZyApiTool {
params.put("sign", sign);
}
private String generateSign(Map<String, Object> params) {
public String generateSign(Map<String, Object> params, boolean isZy) {
// 将参数以参数名的字典升序排序
Map<String, Object> sortParams = new TreeMap<String, Object>(params);
Set<Map.Entry<String, Object>> entrys = sortParams.entrySet();
@@ -193,7 +200,7 @@ public class ZyApiTool {
for (Map.Entry<String, Object> entry : entrys) {
baseString.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
baseString.append("key=").append(zyConfig.getAppId());
baseString.append("key=").append(isZy ? zyConfig.getAppId() : zyConfig.getSelfAppId());
String signStr = baseString.toString();
String digestHex = DigestUtils.md5Hex(signStr);
log.info("|{}|加密前的参数为|{}|加密后的参数为|{}|", TAG, signStr, digestHex);
@@ -1,39 +1,56 @@
package com.bsd.pjcloud.admin;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.thirdparty.ThirdPartyApp;
import com.bsd.pjcloud.thirdparty.config.ZyConfig;
import com.bsd.pjcloud.thirdparty.constant.ThirdZyBizEnumType;
import com.bsd.pjcloud.thirdparty.dto.zy.foreign.ZyForeignSyncNativeCardTradeInfoDto;
import com.bsd.pjcloud.thirdparty.dto.zy.mer.ZyMerSyncAccClassInfoDto;
import com.bsd.pjcloud.thirdparty.dto.zy.mer.ZyMerSyncAccountInfoDto;
import com.bsd.pjcloud.thirdparty.dto.zy.mer.ZyMerSyncDealerInfoDto;
import com.bsd.pjcloud.thirdparty.dto.zy.mer.ZyMerSyncEnterpriseInfoDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfCorrectDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfGetTokenDto;
import com.bsd.pjcloud.thirdparty.dto.zy.self.ZySelfPayDto;
import com.bsd.pjcloud.thirdparty.dto.zy.stride.ZyStrideAuthenticationDto;
import com.bsd.pjcloud.thirdparty.dto.zy.stride.ZyStrideConsumptionDto;
import com.bsd.pjcloud.thirdparty.dto.zy.stride.ZyStrideCorrectDto;
import com.bsd.pjcloud.thirdparty.entity.zy.ThirdZyIdDictEntity;
import com.bsd.pjcloud.thirdparty.mapper.zy.ThirdZyIdDictMapper;
import com.bsd.pjcloud.thirdparty.service.impl.ThirdZyForeignService;
import com.bsd.pjcloud.thirdparty.service.impl.ThirdZyMerService;
import com.bsd.pjcloud.thirdparty.service.impl.ThirdZySelfService;
import com.bsd.pjcloud.thirdparty.service.impl.ThirdZyStrideService;
import com.bsd.pjcloud.thirdparty.utils.zy.api.ZyApiTool;
import com.bsd.pjcloud.thirdparty.vo.zy.foreign.ZyForeignGetRegionIdByTokenVo;
import com.bsd.pjcloud.thirdparty.vo.zy.foreign.ZyForeignSyncNativeCardTradeInfoVo;
import com.bsd.pjcloud.thirdparty.vo.zy.mer.*;
import com.bsd.pjcloud.thirdparty.vo.zy.self.ZySelfGetTokenVo;
import com.bsd.pjcloud.thirdparty.vo.zy.stride.ZyStrideAuthenticationVo;
import com.bsd.pjcloud.thirdparty.vo.zy.stride.ZyStrideConsumptionVo;
import com.bsd.pjcloud.thirdparty.vo.zy.stride.ZyStrideCorrectVo;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.List;
import java.util.Map;
@SpringBootTest(classes = ThirdPartyApp.class)
public class ZyTest {
@Resource
private ZyApiTool zyApiTool;
@Autowired
private ZyConfig zyConfig;
@Resource
private ThirdZyMerService zyMerService;
@@ -41,9 +58,70 @@ public class ZyTest {
private ThirdZyForeignService zyForeignService;
@Resource
private ThirdZyStrideService zyStrideService;
@Resource
private ThirdZySelfService zySelfService;
@Resource
private ThirdZyIdDictMapper zyIdDictMapper;
/************************** start mer start **************************/
@Test
public void selfPay() throws Exception {
String dzcUserId = "1875049673022279681";
String dzcWalletId = "1877309001545244673";
String date = LocalDateTimeUtil.format(LocalDateTimeUtil.now(), DatePattern.NORM_DATETIME_PATTERN);
ThirdZyIdDictEntity dzcUserDict = zyIdDictMapper.getBySelfId(ThirdZyBizEnumType.SYNC_ACCOUNT_INFO, dzcUserId);
ZySelfGetTokenDto tokenParams = new ZySelfGetTokenDto();
tokenParams.setAppid(zyConfig.getSelfAppId());
tokenParams.setAppsecret(zyConfig.getSelfAppSecret());
ZySelfGetTokenVo token = zySelfService.getToken(tokenParams);
String accessToken = token.getAccess_token();
ZySelfPayDto params = ZySelfPayDto
.builder()
.accNum(dzcUserDict.getZyId())
.cardAccNum(dzcWalletId)
.amount("10")
.serialNum("01234567890123456789")
.dealTime(date)
.opId("0123456789")
.build();
Map<String, Object> paramsMap = BeanUtil.beanToMap(params);
Map<String, Object> body = zyApiTool.getSelfEncryptionMap(paramsMap, "accNum", "cardAccNum", "amount", "serialNum", "dealTime", "opId");
ZySelfPayDto bodyObj = JSONUtil.toBean(JSONUtil.toJsonStr(body), ZySelfPayDto.class);
Map<String, Object> pay = zySelfService.pay(bodyObj, accessToken);
}
@Test
public void selfRefund() throws Exception {
String orderId = "1897311229083856897";
String orderNo = "01234567890123456789";
ZySelfGetTokenDto tokenParams = new ZySelfGetTokenDto();
tokenParams.setAppid(zyConfig.getSelfAppId());
tokenParams.setAppsecret(zyConfig.getSelfAppSecret());
ZySelfGetTokenVo token = zySelfService.getToken(tokenParams);
String accessToken = token.getAccess_token();
ZySelfCorrectDto params = ZySelfCorrectDto
.builder()
.serialNum(orderNo)
.correctSerialNum(orderId)
.amount("10")
.opId("01234567890123456789")
.build();
Map<String, Object> paramsMap = BeanUtil.beanToMap(params);
Map<String, Object> body = zyApiTool.getSelfEncryptionMap(paramsMap, "serialNum", "correctSerialNum", "amount", "opId");
ZySelfCorrectDto bodyObj = JSONUtil.toBean(JSONUtil.toJsonStr(body), ZySelfCorrectDto.class);
Map<String, Object> pay = zySelfService.correct(bodyObj, accessToken);
}
/**
* 获取token
*/
@@ -2,6 +2,7 @@ package com.bsd.pjcloud.wallet.api.feign;
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.wallet.api.dto.recharge.WalletRechargeRefundDto;
import com.bsd.pjcloud.wallet.api.vo.recharge.WalletRechargeVo;
import org.springframework.cloud.openfeign.FeignClient;
@@ -17,6 +18,7 @@ public interface RemoteWalletRechargeService {
* @param dto
* @return
*/
@NoToken
@PostMapping("/wallet-recharge/refund")
R<WalletRechargeVo> refund(@RequestBody WalletRechargeRefundDto dto);
@@ -44,6 +44,7 @@ public class WalletRechargeController {
private final WalletRechargeService walletRechargeService;
/* ************************************* start 远程调用 start ************************************* */
@Inner
@Operation(summary = "远程调用-退款", description = "远程调用-退款")
@PostMapping("/refund")
public R<WalletRechargeVo> refund(@Valid @RequestBody WalletRechargeRefundDto dto) {
@@ -119,12 +119,12 @@ public class MchManageServiceImpl extends ServiceImpl<MchManageMapper, MchManage
@Override
public void delByIds(ArrayList<Long> list) {
if (ObjectUtil.isEmpty(list)) return;
baseMapper.deleteByIds(list);
// 删除缓存
list.forEach(v -> {
redisTemplate.opsForValue().getAndDelete(CacheConstants.WALLET_MCH + v);
walletThirdZyService.syncAllMch(v, Boolean.TRUE);
});
baseMapper.deleteByIds(list);
}
@Override
@@ -92,8 +92,10 @@ public class WalletThirdZyServiceImpl implements WalletThirdZyService {
syncList.add(entity);
}
try {
ZyMerSyncDealerInfoVo res = thirdZyService.syncDealerInfo(syncList).getData();
if (ObjectUtil.isEmpty(res)) return;
if (ObjectUtil.isNotEmpty(syncList)) {
ZyMerSyncDealerInfoVo res = thirdZyService.syncDealerInfo(syncList).getData();
if (ObjectUtil.isEmpty(res)) return;
}
} catch (Exception e) {
log.error("|{}syncAllMch 调用第三方接口错误|", TAG);
}
@@ -135,8 +137,10 @@ public class WalletThirdZyServiceImpl implements WalletThirdZyService {
syncList.add(entity);
}
try {
ZyMerSyncEnterpriseInfoVo res = thirdZyService.syncEnterpriseInfoApi(syncList).getData();
if (ObjectUtil.isEmpty(res)) return;
if (ObjectUtil.isNotEmpty(syncList)) {
ZyMerSyncEnterpriseInfoVo res = thirdZyService.syncEnterpriseInfoApi(syncList).getData();
if (ObjectUtil.isEmpty(res)) return;
}
} catch (Exception e) {
log.error("|{}syncAllDept 调用第三方接口错误|", TAG);
}
@@ -171,8 +175,10 @@ public class WalletThirdZyServiceImpl implements WalletThirdZyService {
syncList.add(entity);
}
try {
ZyMerSyncAccClassInfoVo res = thirdZyService.syncAccClassInfoApi(syncList).getData();
if (ObjectUtil.isEmpty(res)) return;
if (ObjectUtil.isNotEmpty(syncList)) {
ZyMerSyncAccClassInfoVo res = thirdZyService.syncAccClassInfoApi(syncList).getData();
if (ObjectUtil.isEmpty(res)) return;
}
} catch (Exception e) {
log.error("|{}syncAllRole 调用第三方接口错误|", TAG);
}
@@ -184,7 +190,7 @@ public class WalletThirdZyServiceImpl implements WalletThirdZyService {
public void syncAllUser(Long userId) {
Page page = new Page();
page.setCurrent(1);
page.setSize(10);
page.setSize(100);
// 查询身份信息
List<SysRole> roleList = remoteRoleService.findRolesByCodes(List.of(DEFAULT_USER_ROLE_CODE)).getData();
if (ObjectUtil.isEmpty(roleList)) {
@@ -245,15 +251,18 @@ public class WalletThirdZyServiceImpl implements WalletThirdZyService {
item.setCardAccNum(v.getId());
item.setCardSID(v.getCardNumber());
item.setCardStatus(getCardStatus(v.getStatus()));
item.setEPID(mch.getDeptId().toString());
item.setEPID(user.getSysUser().getDeptId().toString());
item.setPerCode(v.getUserId().toString());
item.setAccClassID(roleId.toString());
item.setPhoneNo(v.getUserMobile());
item.setFixId(syncAllMchVersion);
syncList.add(item);
}
try {
ZyMerSyncAccountInfoVo.DataVo res = thirdZyService.syncAccountInfoApi(syncList).getData();
if (ObjectUtil.isEmpty(res)) return false;
if (ObjectUtil.isNotEmpty(syncList)) {
ZyMerSyncAccountInfoVo.DataVo res = thirdZyService.syncAccountInfoApi(syncList).getData();
if (ObjectUtil.isEmpty(res)) return false;
}
} catch (Exception e) {
log.error("|{}syncAllUserGroup 调用第三方接口错误|", TAG);
return false;