mirror of
https://gitee.com/technical-laohu/mpay_v2_webman.git
synced 2026-05-17 06:20:25 +08:00
feat: 完善支付通道和收款监听链路
新增 ChannelNotifyPayloadInterface 等支付插件通知契约,规范 pay_no 定位和插件返回校验。 新增微信、支付宝、收钱吧、Postar 个人收款插件适配,支持余额识别与备注识别。 新增 receipt-watcher 后端进程、Redis 队列 job 和平台事件监听,覆盖收款流水通知、商户通知、退款派发、转账派发与清算完成。 补齐个人收款监听相关系统配置、仓储、服务费冻结明细、订单后台操作和通道测试能力。 重构支付单创建、回调、费用、风控、结算和通道统计链路,统一状态流转与幂等处理。
This commit is contained in:
@@ -44,43 +44,15 @@ final class AuthConstant
|
||||
*/
|
||||
public const CREDENTIAL_STATUS_ENABLED = 1;
|
||||
|
||||
/**
|
||||
* API 签名类型:MD5。
|
||||
*/
|
||||
public const API_SIGN_TYPE_MD5 = 0;
|
||||
|
||||
/**
|
||||
* API 签名类型:SHA256WithRSA。
|
||||
*/
|
||||
public const API_SIGN_TYPE_SHA256_WITH_RSA = 1;
|
||||
|
||||
/**
|
||||
* API 签名类型名称:MD5。
|
||||
*/
|
||||
public const API_SIGN_NAME_MD5 = 'MD5';
|
||||
|
||||
/**
|
||||
* API 签名类型名称:SHA256WithRSA。
|
||||
* API 签名类型名称:RSA。
|
||||
*/
|
||||
public const API_SIGN_NAME_SHA256_WITH_RSA = 'SHA256WithRSA';
|
||||
|
||||
/**
|
||||
* API 签名类型归一化名称:SHA256WITHRSA。
|
||||
*/
|
||||
public const API_SIGN_NORMALIZED_SHA256_WITH_RSA = 'SHA256WITHRSA';
|
||||
|
||||
/**
|
||||
* 获取签名类型映射。
|
||||
*
|
||||
* @return array<int, string> 签名类型名称表
|
||||
*/
|
||||
public static function signTypeMap(): array
|
||||
{
|
||||
return [
|
||||
self::API_SIGN_TYPE_MD5 => self::API_SIGN_NAME_MD5,
|
||||
self::API_SIGN_TYPE_SHA256_WITH_RSA => self::API_SIGN_NAME_SHA256_WITH_RSA,
|
||||
];
|
||||
}
|
||||
public const API_SIGN_NAME_RSA = 'RSA';
|
||||
|
||||
/**
|
||||
* 获取接口凭证状态映射。
|
||||
@@ -108,5 +80,3 @@ final class AuthConstant
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
92
app/common/constant/EpayProtocolConstant.php
Normal file
92
app/common/constant/EpayProtocolConstant.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constant;
|
||||
|
||||
/**
|
||||
* ePay 协议固定值。
|
||||
*/
|
||||
final class EpayProtocolConstant
|
||||
{
|
||||
/**
|
||||
* 旧版 ePay 协议版本。
|
||||
*/
|
||||
public const VERSION_V1 = 'v1';
|
||||
|
||||
/**
|
||||
* 新版 ePay 协议版本。
|
||||
*/
|
||||
public const VERSION_V2 = 'v2';
|
||||
|
||||
/**
|
||||
* 页面跳转提交。
|
||||
*/
|
||||
public const SUBMIT_TYPE_PAGE = 'page';
|
||||
|
||||
/**
|
||||
* API 直连提交。
|
||||
*/
|
||||
public const SUBMIT_TYPE_API = 'api';
|
||||
|
||||
/**
|
||||
* 电脑浏览器。
|
||||
*/
|
||||
public const DEVICE_PC = 'pc';
|
||||
|
||||
/**
|
||||
* 手机浏览器。
|
||||
*/
|
||||
public const DEVICE_MOBILE = 'mobile';
|
||||
|
||||
/**
|
||||
* 手机 QQ 内浏览器。
|
||||
*/
|
||||
public const DEVICE_QQ = 'qq';
|
||||
|
||||
/**
|
||||
* 微信内浏览器。
|
||||
*/
|
||||
public const DEVICE_WECHAT = 'wechat';
|
||||
|
||||
/**
|
||||
* 支付宝客户端。
|
||||
*/
|
||||
public const DEVICE_ALIPAY = 'alipay';
|
||||
|
||||
/**
|
||||
* 仅返回支付跳转 URL。
|
||||
*/
|
||||
public const DEVICE_JUMP = 'jump';
|
||||
|
||||
/**
|
||||
* V1 支持的设备类型。
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public static function v1Devices(): array
|
||||
{
|
||||
return [
|
||||
self::DEVICE_PC,
|
||||
self::DEVICE_MOBILE,
|
||||
self::DEVICE_QQ,
|
||||
self::DEVICE_WECHAT,
|
||||
self::DEVICE_ALIPAY,
|
||||
self::DEVICE_JUMP,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* V2 支持的设备类型。
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public static function v2Devices(): array
|
||||
{
|
||||
return [
|
||||
self::DEVICE_PC,
|
||||
self::DEVICE_MOBILE,
|
||||
self::DEVICE_QQ,
|
||||
self::DEVICE_WECHAT,
|
||||
self::DEVICE_ALIPAY,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,11 @@ final class EventConstant
|
||||
*/
|
||||
public const PAYMENT_PAY_ORDER_TIMEOUT = 'payment.pay_order.timeout';
|
||||
|
||||
/**
|
||||
* 网页流水监听相关配置已变更。
|
||||
*/
|
||||
public const PAYMENT_RECEIPT_WATCHER_CONFIG_CHANGED = 'payment.receipt_watcher.config.changed';
|
||||
|
||||
/**
|
||||
* 退款单进入成功态。
|
||||
*/
|
||||
|
||||
63
app/common/constant/FundFreezeConstant.php
Normal file
63
app/common/constant/FundFreezeConstant.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constant;
|
||||
|
||||
/**
|
||||
* 商户资金冻结常量。
|
||||
*
|
||||
* 冻结记录是提现、退款、通知等高风险动作的统一风控依据。
|
||||
*/
|
||||
final class FundFreezeConstant
|
||||
{
|
||||
/**
|
||||
* 支付订单冻结。
|
||||
*/
|
||||
public const TYPE_PAY_ORDER = 1;
|
||||
|
||||
/**
|
||||
* 人工指定金额冻结。
|
||||
*/
|
||||
public const TYPE_MANUAL_AMOUNT = 2;
|
||||
|
||||
/**
|
||||
* 支付平台服务费预冻结。
|
||||
*/
|
||||
public const TYPE_PAY_FEE = 3;
|
||||
|
||||
/**
|
||||
* 冻结中。
|
||||
*/
|
||||
public const STATUS_ACTIVE = 1;
|
||||
|
||||
/**
|
||||
* 已解冻。
|
||||
*/
|
||||
public const STATUS_RELEASED = 2;
|
||||
|
||||
/**
|
||||
* 获取冻结类型文案。
|
||||
*
|
||||
* @return array<int, string> 冻结类型文案
|
||||
*/
|
||||
public static function typeMap(): array
|
||||
{
|
||||
return [
|
||||
self::TYPE_PAY_ORDER => '支付订单',
|
||||
self::TYPE_MANUAL_AMOUNT => '人工指定金额',
|
||||
self::TYPE_PAY_FEE => '支付平台服务费',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取冻结状态文案。
|
||||
*
|
||||
* @return array<int, string> 冻结状态文案
|
||||
*/
|
||||
public static function statusMap(): array
|
||||
{
|
||||
return [
|
||||
self::STATUS_ACTIVE => '冻结中',
|
||||
self::STATUS_RELEASED => '已解冻',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,14 @@ final class LedgerConstant
|
||||
* 转账释放流水。
|
||||
*/
|
||||
public const BIZ_TYPE_TRANSFER_RELEASE = 8;
|
||||
/**
|
||||
* 风控资金冻结流水。
|
||||
*/
|
||||
public const BIZ_TYPE_RISK_FREEZE = 9;
|
||||
/**
|
||||
* 风控资金释放流水。
|
||||
*/
|
||||
public const BIZ_TYPE_RISK_RELEASE = 10;
|
||||
|
||||
/**
|
||||
* 账务事件的创建动作。
|
||||
@@ -87,6 +95,8 @@ final class LedgerConstant
|
||||
self::BIZ_TYPE_TRANSFER_DEDUCT => '转账扣款',
|
||||
self::BIZ_TYPE_TRANSFER_FEE => '转账手续费',
|
||||
self::BIZ_TYPE_TRANSFER_RELEASE => '转账释放',
|
||||
self::BIZ_TYPE_RISK_FREEZE => '风控冻结',
|
||||
self::BIZ_TYPE_RISK_RELEASE => '风控释放',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -119,4 +129,3 @@ final class LedgerConstant
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,16 @@ final class NotifyConstant
|
||||
*/
|
||||
public const EVENT_SETTLEMENT_SUCCESS = 'SETTLEMENT_SUCCESS';
|
||||
|
||||
/**
|
||||
* 商户通知成功响应。
|
||||
*/
|
||||
public const MERCHANT_SUCCESS_RESPONSE = 'success';
|
||||
|
||||
/**
|
||||
* ePay 通知交易成功状态。
|
||||
*/
|
||||
public const EPAY_TRADE_STATUS_SUCCESS = 'TRADE_SUCCESS';
|
||||
|
||||
/**
|
||||
* 异步通知类型。
|
||||
*/
|
||||
|
||||
88
app/common/constant/PayOrderActionConstant.php
Normal file
88
app/common/constant/PayOrderActionConstant.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constant;
|
||||
|
||||
/**
|
||||
* 支付订单后台操作常量。
|
||||
*
|
||||
* 操作码是后端与管理前端之间的展示协议,前端只根据本类对应的
|
||||
* actions 结果渲染按钮,不再自行硬编码订单状态规则。
|
||||
*/
|
||||
final class PayOrderActionConstant
|
||||
{
|
||||
/**
|
||||
* 手动补单。
|
||||
*/
|
||||
public const MANUAL_SUCCESS = 'manual_success';
|
||||
|
||||
/**
|
||||
* 重新通知商户。
|
||||
*/
|
||||
public const RENOTIFY = 'renotify';
|
||||
|
||||
/**
|
||||
* 主动查询上游。
|
||||
*/
|
||||
public const ACTIVE_QUERY = 'active_query';
|
||||
|
||||
/**
|
||||
* API 退款。
|
||||
*/
|
||||
public const API_REFUND = 'api_refund';
|
||||
|
||||
/**
|
||||
* 手动退款。
|
||||
*/
|
||||
public const MANUAL_REFUND = 'manual_refund';
|
||||
|
||||
/**
|
||||
* 冻结订单。
|
||||
*/
|
||||
public const FREEZE = 'freeze';
|
||||
|
||||
/**
|
||||
* 解冻订单。
|
||||
*/
|
||||
public const UNFREEZE = 'unfreeze';
|
||||
|
||||
/**
|
||||
* 订单未冻结。
|
||||
*/
|
||||
public const FREEZE_STATUS_NORMAL = 0;
|
||||
|
||||
/**
|
||||
* 订单已冻结。
|
||||
*/
|
||||
public const FREEZE_STATUS_FROZEN = 1;
|
||||
|
||||
/**
|
||||
* 获取后台操作文案。
|
||||
*
|
||||
* @return array<string, string> 操作文案映射
|
||||
*/
|
||||
public static function actionLabelMap(): array
|
||||
{
|
||||
return [
|
||||
self::MANUAL_SUCCESS => '手动补单',
|
||||
self::RENOTIFY => '重新通知',
|
||||
self::ACTIVE_QUERY => '主动查询',
|
||||
self::API_REFUND => 'API退款',
|
||||
self::MANUAL_REFUND => '手动退款',
|
||||
self::FREEZE => '冻结订单',
|
||||
self::UNFREEZE => '解冻订单',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取冻结状态文案。
|
||||
*
|
||||
* @return array<int, string> 冻结状态文案映射
|
||||
*/
|
||||
public static function freezeStatusMap(): array
|
||||
{
|
||||
return [
|
||||
self::FREEZE_STATUS_NORMAL => '正常',
|
||||
self::FREEZE_STATUS_FROZEN => '已冻结',
|
||||
];
|
||||
}
|
||||
}
|
||||
42
app/common/constant/PaymentQueueConstant.php
Normal file
42
app/common/constant/PaymentQueueConstant.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace app\common\constant;
|
||||
|
||||
/**
|
||||
* 支付队列名称常量。
|
||||
*
|
||||
* 队列名是生产者与消费者之间的协议,不建议写在业务服务或消费者里。
|
||||
* 新增支付域队列时优先在本类登记,再分别实现投递服务与消费者。
|
||||
*/
|
||||
final class PaymentQueueConstant
|
||||
{
|
||||
/**
|
||||
* 商户异步通知队列名。
|
||||
*/
|
||||
public const MERCHANT_NOTIFY = 'merchant_notify';
|
||||
|
||||
/**
|
||||
* 退款上游派发队列名。
|
||||
*/
|
||||
public const REFUND_DISPATCH = 'refund_dispatch';
|
||||
|
||||
/**
|
||||
* 转账上游派发队列名。
|
||||
*/
|
||||
public const TRANSFER_DISPATCH = 'transfer_dispatch';
|
||||
|
||||
/**
|
||||
* 转账上游查单队列名。
|
||||
*/
|
||||
public const TRANSFER_QUERY = 'transfer_query';
|
||||
|
||||
/**
|
||||
* 清算自动入账队列名。
|
||||
*/
|
||||
public const SETTLEMENT_COMPLETE = 'settlement_complete';
|
||||
|
||||
/**
|
||||
* 网页流水监听通知队列名。
|
||||
*/
|
||||
public const RECEIPT_FLOW_NOTIFY = 'receipt_flow_notify';
|
||||
}
|
||||
@@ -15,7 +15,7 @@ final class RouteConstant
|
||||
public const CHANNEL_TYPE_PLATFORM_COLLECT = 0;
|
||||
|
||||
/**
|
||||
* 商户自有通道类型。
|
||||
* 商户自收通道类型。
|
||||
*/
|
||||
public const CHANNEL_TYPE_MERCHANT_SELF = 1;
|
||||
|
||||
@@ -53,7 +53,7 @@ final class RouteConstant
|
||||
{
|
||||
return [
|
||||
self::CHANNEL_TYPE_PLATFORM_COLLECT => '平台代收',
|
||||
self::CHANNEL_TYPE_MERCHANT_SELF => '商户自有',
|
||||
self::CHANNEL_TYPE_MERCHANT_SELF => '商户自收',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -86,4 +86,3 @@ final class RouteConstant
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -54,21 +54,21 @@ final class TradeConstant
|
||||
public const ORDER_STATUS_TIMEOUT = 5;
|
||||
|
||||
/**
|
||||
* 手续费未处理。
|
||||
* 平台服务费未处理。
|
||||
*/
|
||||
public const FEE_STATUS_NONE = 0;
|
||||
public const SERVICE_FEE_STATUS_NONE = 0;
|
||||
/**
|
||||
* 手续费已冻结。
|
||||
* 平台服务费已冻结。
|
||||
*/
|
||||
public const FEE_STATUS_FROZEN = 1;
|
||||
public const SERVICE_FEE_STATUS_FROZEN = 1;
|
||||
/**
|
||||
* 手续费已扣除。
|
||||
* 平台服务费已扣除。
|
||||
*/
|
||||
public const FEE_STATUS_DEDUCTED = 2;
|
||||
public const SERVICE_FEE_STATUS_DEDUCTED = 2;
|
||||
/**
|
||||
* 手续费已释放。
|
||||
* 平台服务费已释放。
|
||||
*/
|
||||
public const FEE_STATUS_RELEASED = 3;
|
||||
public const SERVICE_FEE_STATUS_RELEASED = 3;
|
||||
|
||||
/**
|
||||
* 清算状态为空。
|
||||
@@ -142,17 +142,17 @@ final class TradeConstant
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手续费状态映射。
|
||||
* 获取平台服务费状态映射。
|
||||
*
|
||||
* @return array<int, string> 手续费状态名称表
|
||||
* @return array<int, string> 平台服务费状态名称表
|
||||
*/
|
||||
public static function feeStatusMap(): array
|
||||
public static function serviceFeeStatusMap(): array
|
||||
{
|
||||
return [
|
||||
self::FEE_STATUS_NONE => '无',
|
||||
self::FEE_STATUS_FROZEN => '冻结',
|
||||
self::FEE_STATUS_DEDUCTED => '已扣',
|
||||
self::FEE_STATUS_RELEASED => '已释放',
|
||||
self::SERVICE_FEE_STATUS_NONE => '无',
|
||||
self::SERVICE_FEE_STATUS_FROZEN => '冻结',
|
||||
self::SERVICE_FEE_STATUS_DEDUCTED => '已扣',
|
||||
self::SERVICE_FEE_STATUS_RELEASED => '已释放',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -301,5 +301,3 @@ final class TradeConstant
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -11,14 +11,22 @@ final class TransferConstant
|
||||
* 转账待处理状态。
|
||||
*/
|
||||
public const TRANSFER_STATUS_PENDING = 0;
|
||||
/**
|
||||
* 转账处理中状态。
|
||||
*/
|
||||
public const TRANSFER_STATUS_PROCESSING = 1;
|
||||
/**
|
||||
* 转账成功状态。
|
||||
*/
|
||||
public const TRANSFER_STATUS_SUCCESS = 1;
|
||||
public const TRANSFER_STATUS_SUCCESS = 2;
|
||||
/**
|
||||
* 转账失败状态。
|
||||
*/
|
||||
public const TRANSFER_STATUS_FAILED = 2;
|
||||
public const TRANSFER_STATUS_FAILED = 3;
|
||||
/**
|
||||
* 转账关闭状态。
|
||||
*/
|
||||
public const TRANSFER_STATUS_CLOSED = 4;
|
||||
|
||||
/**
|
||||
* 获取转账状态映射。
|
||||
@@ -29,8 +37,25 @@ final class TransferConstant
|
||||
{
|
||||
return [
|
||||
self::TRANSFER_STATUS_PENDING => '待处理',
|
||||
self::TRANSFER_STATUS_PROCESSING => '处理中',
|
||||
self::TRANSFER_STATUS_SUCCESS => '成功',
|
||||
self::TRANSFER_STATUS_FAILED => '失败',
|
||||
self::TRANSFER_STATUS_CLOSED => '关闭',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为转账终态。
|
||||
*
|
||||
* @param int $status 转账状态
|
||||
* @return bool 是否终态
|
||||
*/
|
||||
public static function isTerminalStatus(int $status): bool
|
||||
{
|
||||
return in_array($status, [
|
||||
self::TRANSFER_STATUS_SUCCESS,
|
||||
self::TRANSFER_STATUS_FAILED,
|
||||
self::TRANSFER_STATUS_CLOSED,
|
||||
], true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user