feat:适配聚合支付

This commit is contained in:
dzc committed 2026-10-20 13:40:25 +08:00
1 parent c0d503f00e
commit 667b87fc00
41 files changed
+1391 -197

No files matched your search

@@ -27,6 +27,11 @@ import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(contextId = "remoterThirdAppPlusPayService", value = ServiceNameConstants.THIRDPARTY_SERVICE)
public interface RemoterThirdAppPlusPayService {
/** 为当前租户签发商户静态 H5 收款入口,签名密钥只保留在 third 服务。 */
@NoToken
@GetMapping("/pay-remoter/merchant-collection-url")
R<String> merchantCollectionUrl(@RequestParam("mchId") Long mchId);
/**
* 编辑商户的回调
*/
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.thirdparty.constant.pay;
import lombok.AllArgsConstructor;
import lombok.Getter;
/** 聚合收银场景;编码同时用于数据库、公开接口和管理端,不能随意改名。 */
@Getter
@AllArgsConstructor
public enum ThirdAggregatePaySceneEnum {
/** 已存在业务订单的聚合支付,金额由内部业务订单确定。 */
ORDER("ORDER"),
/** 无商品订单的线下收款,金额由付款人确认后固定。 */
OFFLINE("OFFLINE");
/** 持久化及跨端协议编码。 */
private final String code;
}
@@ -13,18 +13,28 @@ import java.util.Arrays;
@Getter
public enum ThirdPayOrderBizTypeEnum {
/** 10:App 用户钱包充值,成功后进入充值业务回调。 */
MINI_APP_WALLET_RECHARGE("10", "APP用户钱包充值"),
/** 20:原云消费机付款码支付,保持历史协议。 */
YXFJ_PAY("20", "云消费机付款码支付"),
/** 30:App 商品订单支付,关联既有业务订单。 */
APP_SHOP_PAY("30", "APP支付-购买商品(有订单)"),
/** 40:监护人代充值,保持原充值回调。 */
GUARDIAN_WARD_WALLET_RECHARGE("40", "监护人代被监护人饭卡充值"),
/** 50:现有食堂或超市消费订单支付,聚合订单沿用该编码。 */
XFJ("50", "食堂或者超市的消费机支付"),
/** App 酒店预订支付:业务订单在 supermarket,本服务只记支付流水 */
HOTEL_ORDER_PAY("60", "酒店订单支付"),
/** 商户线下收款,无商品或消费订单;70 是持久化和跨服务业务编码。 */
MCH_OFFLINE_PAY("70", "商户线下收款"),
;
/** 数据库与跨服务协议使用的业务编码,不得随意变更。 */
private final String type;
/** 管理与诊断使用的中文业务描述。 */
private final String description;
/** 按已有协议编码解析支付业务类型,空值保持原有空结果约定。 */
public static ThirdPayOrderBizTypeEnum 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,19 @@
package com.bsd.pjcloud.thirdparty.dto.appplus;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Positive;
import lombok.Data;
import lombok.EqualsAndHashCode;
/** 线下收款创建请求,不允许付款人指定渠道商户、业务类型或业务订单。 */
@Data
@EqualsAndHashCode(callSuper = true)
public class ThirdAggregateMerchantCreateDto extends ThirdAggregateMerchantEntryDto {
/** 付款人确认的人民币整数分;后端还会检查可配置的线下单笔上限。 */
@NotNull @Positive
private Integer amount;
/** 浏览器为一次付款意图生成的 UUID;重试必须复用,不能改变商户或金额。 */
@NotNull @Pattern(regexp = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}")
private String requestId;
}
@@ -0,0 +1,23 @@
package com.bsd.pjcloud.thirdparty.dto.appplus;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Positive;
import lombok.Data;
/** 商户静态收款码凭据,只能由服务端签发,不能作为订单支付授权。 */
@Data
public class ThirdAggregateMerchantEntryDto {
/** 二维码对应的收款商户主键,与签名绑定。 */
@NotNull @Positive
private Long id;
/** 二维码对应的租户主键,验签后恢复该租户上下文。 */
@NotNull @Positive
private Long tenantId;
/** 收款链接协议版本,本轮仅支持 1。 */
@NotNull @Pattern(regexp = "1")
private String v;
/** HMAC-SHA256 小写十六进制签名,绑定用途、版本、租户和商户。 */
@NotNull @Pattern(regexp = "[0-9a-f]{64}")
private String sign;
}
@@ -40,6 +40,10 @@ public class ThirdAggregatePaySessionEntity extends Model<ThirdAggregatePaySessi
@Schema(description = "聚合会话编号")
private String aggregateNo;
/** 聚合场景,ORDER 为业务订单,OFFLINE 为线下收款;历史会话默认为 ORDER。 */
@Schema(description = "聚合场景")
private String aggregateScene;
/**
* 收银 URL 随机访问令牌的 SHA-256 十六进制摘要,用于扫码入口等值查询。
*/
@@ -53,13 +57,13 @@ public class ThirdAggregatePaySessionEntity extends Model<ThirdAggregatePaySessi
private String accessTokenCiphertext;
/**
* 支付业务类型编码,首版固定为云消费机支付业务。
* 支付业务类型编码;订单聚合沿用原业务类型,线下收款固定为 70。
*/
@Schema(description = "支付业务类型编码")
private String bizType;
/**
* 调用方业务订单唯一标识,同一租户内用于支付幂等。
* 业务订单或线下收款请求唯一标识,同一租户内用于支付幂等。
*/
@Schema(description = "支付业务id")
private String bizId;
@@ -48,6 +48,10 @@ public class ThirdPayOrderEntity extends Model<ThirdPayOrderEntity> {
@Schema(description = "支付类型")
private String bizType;
/** 聚合场景,ORDER 为订单聚合、OFFLINE 为线下收款;空值表示非聚合支付。 */
@Schema(description = "聚合场景")
private String aggregateScene;
/**
* 支付相关id
*/
@@ -0,0 +1,28 @@
package com.bsd.pjcloud.thirdparty.vo.appplus.pay;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Map;
/** 通过短期收银票据读取的最小上下文,不返回商户配置或 OAuth 身份。 */
@Data
public class ThirdAggregateH5ContextVo {
/** 服务端保存的 ORDER 或 OFFLINE 场景,不能由 URL 覆盖。 */
private String aggregateScene;
/** 收款商户公开资料。 */
private ThirdAggregateMerchantVo merchant;
/** 已确认且不可编辑的人民币整数分。 */
private Integer amount;
/** 服务端选定的渠道编码,10 为微信、20 为支付宝。 */
private String selectedPlatform;
/** 当前第三方商户支付单号。 */
private String payNo;
/** 聚合会话状态,与既有状态查询接口一致。 */
private String status;
/** 渠道已确认成功时为 true,前端 JSBridge 结果不能替代该值。 */
private boolean paySuccess;
/** 尚可继续支付时提供的最小 JSBridge 参数,终态时为空。 */
private Map<String, Object> launchParams;
/** 当前会话的服务端截止时间。 */
private LocalDateTime expireTime;
}
@@ -0,0 +1,15 @@
package com.bsd.pjcloud.thirdparty.vo.appplus.pay;
import lombok.Data;
import java.time.LocalDateTime;
/** 匿名线下收款的创建结果,前端只能进入服务端固定的 OAuth 收银地址。 */
@Data
public class ThirdAggregateMerchantCreateVo {
/** 用于恢复当前付款意图的聚合会话编号。 */
private String aggregateNo;
/** 现有聚合入口 HTTPS 地址,内含随机访问令牌,不含付款人身份。 */
private String cashierUrl;
/** 服务端会话截止时间,渠道真实状态仍以服务端查单为准。 */
private LocalDateTime expireTime;
}
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.thirdparty.vo.appplus.pay;
import lombok.Data;
import java.util.List;
/** 匿名收银商户视图,不包含支付配置、饭卡密钥、用户或结算资料。 */
@Data
public class ThirdAggregateMerchantVo {
/** 商户主键使用字符串,避免浏览器丢失长整数精度。 */
private String id;
/** 收款商户名称,以钱包服务的当前资料为准。 */
private String name;
/** 商户标识图片地址,未配置时为空,前端使用统一占位图形。 */
private String logoPic;
/** 当前商户已启用的渠道编码,10 微信、20 支付宝;空列表表示暂无可用渠道,不包含渠道凭据。 */
private List<String> supportedPlatforms = List.of();
}
@@ -9,6 +9,9 @@ import lombok.Data;
@Data
public class ThirdPayOrderVo extends ThirdPayOrderEntity {
/** 绑定的聚合会话号,按当前页 payNo 批量补充;非聚合支付为空。 */
private String aggregateNo;
/**
* 支付订单所属商户名称,来源于商户管理服务;商户已删除或不可见时为空。
*/