mirror of
https://gitee.com/technical-laohu/mpay_v2_webman.git
synced 2026-04-26 12:04:28 +08:00
更新统一使用 PHPDoc + PSR-19 标准注释
This commit is contained in:
@@ -22,10 +22,39 @@ use support\Request;
|
||||
use support\Response;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* 旧版 Epay 协议兼容服务。
|
||||
*
|
||||
* 负责将旧协议请求转换为当前支付、退款和查询流程。
|
||||
*
|
||||
* @property MerchantApiCredentialService $merchantApiCredentialService 商户 API 凭证服务
|
||||
* @property PaymentTypeService $paymentTypeService 支付类型服务
|
||||
* @property PayOrderService $payOrderService 支付订单服务
|
||||
* @property PaymentPluginManager $paymentPluginManager 支付插件管理器
|
||||
* @property MerchantAccountRepository $merchantAccountRepository 商户账户仓库
|
||||
* @property BizOrderRepository $bizOrderRepository 业务订单仓库
|
||||
* @property PayOrderRepository $payOrderRepository 支付单仓库
|
||||
* @property SettlementOrderRepository $settlementOrderRepository 结算订单仓库
|
||||
* @property RefundService $refundService 退款服务
|
||||
*/
|
||||
class EpayCompatService extends BaseService
|
||||
{
|
||||
private const API_ACTIONS = ['query', 'settle', 'order', 'orders', 'refund'];
|
||||
|
||||
/**
|
||||
* 构造方法。
|
||||
*
|
||||
* @param MerchantApiCredentialService $merchantApiCredentialService 商户 API 凭证服务
|
||||
* @param PaymentTypeService $paymentTypeService 支付类型服务
|
||||
* @param PayOrderService $payOrderService 支付订单服务
|
||||
* @param PaymentPluginManager $paymentPluginManager 支付插件管理器
|
||||
* @param MerchantAccountRepository $merchantAccountRepository 商户账户仓库
|
||||
* @param BizOrderRepository $bizOrderRepository 业务订单仓库
|
||||
* @param PayOrderRepository $payOrderRepository 支付订单仓库
|
||||
* @param SettlementOrderRepository $settlementOrderRepository 结算订单仓库
|
||||
* @param RefundService $refundService 退款服务
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(
|
||||
protected MerchantApiCredentialService $merchantApiCredentialService,
|
||||
protected PaymentTypeService $paymentTypeService,
|
||||
@@ -39,6 +68,14 @@ class EpayCompatService extends BaseService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理页面跳转支付入口。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @param Request $request 请求对象
|
||||
* @return Response 跳转响应或错误 JSON
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function submit(array $payload, Request $request): Response
|
||||
{
|
||||
try {
|
||||
@@ -58,6 +95,13 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 API 支付入口。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @param Request $request 请求对象
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
public function mapi(array $payload, Request $request): array
|
||||
{
|
||||
try {
|
||||
@@ -68,6 +112,14 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理旧版兼容入口。
|
||||
*
|
||||
* 支持 `query`、`settle`、`order`、`orders` 和 `refund` 五种操作。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
public function api(array $payload): array
|
||||
{
|
||||
$act = strtolower(trim((string) ($payload['act'] ?? '')));
|
||||
@@ -84,6 +136,12 @@ class EpayCompatService extends BaseService
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询商户信息,对应 `act=query`。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
public function queryMerchantInfo(array $payload): array
|
||||
{
|
||||
try {
|
||||
@@ -93,6 +151,7 @@ class EpayCompatService extends BaseService
|
||||
$merchant = $auth['merchant'];
|
||||
$credential = $auth['credential'];
|
||||
$account = $this->merchantAccountRepository->findByMerchantId($merchantId);
|
||||
// 旧协议会同时返回总单量、今日单量和昨日单量,便于上游直接做商户概览。
|
||||
$todayDate = FormatHelper::timestamp(time(), 'Y-m-d');
|
||||
$lastDayDate = FormatHelper::timestamp(strtotime('-1 day'), 'Y-m-d');
|
||||
$totalOrders = (int) $this->payOrderRepository->query()->where('merchant_id', $merchantId)->count();
|
||||
@@ -117,6 +176,12 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询结算记录列表,对应 `act=settle`。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
public function querySettlementList(array $payload): array
|
||||
{
|
||||
try {
|
||||
@@ -125,6 +190,7 @@ class EpayCompatService extends BaseService
|
||||
$this->merchantApiCredentialService->authenticateByKey($merchantId, $key);
|
||||
$rows = $this->settlementOrderRepository->query()->where('merchant_id', $merchantId)->orderByDesc('id')->get();
|
||||
|
||||
// 旧协议列表只需要基础字段和金额文本,这里直接整理成可展示数组。
|
||||
return [
|
||||
'code' => 1,
|
||||
'msg' => '查询结算记录成功!',
|
||||
@@ -147,6 +213,12 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单个订单,对应 `act=order`。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
public function queryOrder(array $payload): array
|
||||
{
|
||||
try {
|
||||
@@ -158,18 +230,26 @@ class EpayCompatService extends BaseService
|
||||
return ['code' => 0, 'msg' => '订单不存在'];
|
||||
}
|
||||
|
||||
// 旧协议查询单号时,要把支付单和业务单合并成同一份响应结构。
|
||||
return ['code' => 1, 'msg' => '查询订单号成功!'] + $this->formatEpayOrderRow($context['pay_order'], $context['biz_order']);
|
||||
} catch (Throwable $e) {
|
||||
return ['code' => 0, 'msg' => $this->normalizeErrorMessage($e, '查询失败')];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量查询订单,对应 `act=orders`。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
public function queryOrders(array $payload): array
|
||||
{
|
||||
try {
|
||||
$merchantId = (int) ($payload['pid'] ?? 0);
|
||||
$key = trim((string) ($payload['key'] ?? ''));
|
||||
$this->merchantApiCredentialService->authenticateByKey($merchantId, $key);
|
||||
// 旧接口默认只允许一次拉少量订单,这里沿用上限 50 的兼容口径。
|
||||
$limit = min(50, max(1, (int) ($payload['limit'] ?? 20)));
|
||||
$page = max(1, (int) ($payload['page'] ?? 1));
|
||||
$paginator = $this->payOrderRepository->query()->where('merchant_id', $merchantId)->orderByDesc('id')->paginate($limit, ['*'], 'page', $page);
|
||||
@@ -177,6 +257,7 @@ class EpayCompatService extends BaseService
|
||||
return [
|
||||
'code' => 1,
|
||||
'msg' => '查询结算记录成功!',
|
||||
// 批量查询和单条查询共用同一套格式化器,避免字段口径不一致。
|
||||
'data' => array_map(function ($row): array {
|
||||
return $this->formatEpayOrderRow($row, $this->bizOrderRepository->findByBizNo((string) $row->biz_no));
|
||||
}, $paginator->items()),
|
||||
@@ -186,12 +267,19 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交退款申请,对应 `act=refund`。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
public function createRefund(array $payload): array
|
||||
{
|
||||
try {
|
||||
$merchantId = (int) ($payload['pid'] ?? 0);
|
||||
$key = trim((string) ($payload['key'] ?? ''));
|
||||
$this->merchantApiCredentialService->authenticateByKey($merchantId, $key);
|
||||
// 先确认退款目标单据归属当前商户,避免旧协议拿着别人的单号误发退款。
|
||||
$context = $this->resolvePayOrderContext($merchantId, $payload);
|
||||
if (!$context) {
|
||||
return ['code' => 1, 'msg' => '订单不存在'];
|
||||
@@ -213,6 +301,7 @@ class EpayCompatService extends BaseService
|
||||
]);
|
||||
|
||||
$plugin = $this->paymentPluginManager->createByPayOrder($payOrder, true);
|
||||
// 不同插件返回的退款结果字段不完全一致,这里仍按旧协议的退款参数重新组织一次。
|
||||
$pluginResult = $plugin->refund([
|
||||
'order_id' => (string) $payOrder->pay_no,
|
||||
'pay_no' => (string) $payOrder->pay_no,
|
||||
@@ -227,6 +316,7 @@ class EpayCompatService extends BaseService
|
||||
]);
|
||||
|
||||
if (!$this->isPluginSuccess($pluginResult)) {
|
||||
// 渠道明确失败时,先把退款单推进失败态,再把旧协议响应收口成失败文案。
|
||||
$this->refundService->markRefundFailed((string) $refundOrder->refund_no, [
|
||||
'failed_at' => $this->now(),
|
||||
'last_error' => (string) ($pluginResult['msg'] ?? $pluginResult['message'] ?? '退款失败'),
|
||||
@@ -249,8 +339,18 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预处理支付提交请求。
|
||||
*
|
||||
* 这里负责把旧协议载荷转换为当前支付单创建所需的数据结构。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @param Request $request 请求对象
|
||||
* @return array<string, mixed> 预处理数据
|
||||
*/
|
||||
private function prepareSubmitAttempt(array $payload, Request $request): array
|
||||
{
|
||||
// 先把旧协议载荷转换成当前系统的统一入参,再交给支付单主流程处理。
|
||||
$normalized = $this->normalizeSubmitPayload($payload, $request);
|
||||
$result = $this->payOrderService->preparePayAttempt($normalized);
|
||||
$payOrder = $result['pay_order'];
|
||||
@@ -265,8 +365,19 @@ class EpayCompatService extends BaseService
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化提交支付参数。
|
||||
*
|
||||
* 这里会完成签名校验、金额转分、支付方式解析,并把旧协议字段写入扩展信息。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @param Request $request 请求对象
|
||||
* @return array<string, mixed> 当前支付单创建参数
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function normalizeSubmitPayload(array $payload, Request $request): array
|
||||
{
|
||||
// 提交入口也必须先验签,避免旧协议请求绕过统一的身份校验。
|
||||
$this->merchantApiCredentialService->verifyMd5Sign($payload);
|
||||
$typeCode = trim((string) ($payload['type'] ?? ''));
|
||||
$merchantOrderNo = trim((string) ($payload['out_trade_no'] ?? ''));
|
||||
@@ -296,6 +407,7 @@ class EpayCompatService extends BaseService
|
||||
'submitted_type' => $typeCode,
|
||||
'submit_mode' => $typeCode === '' ? 'cashier' : 'direct',
|
||||
'request_method' => strtoupper((string) ($_SERVER['REQUEST_METHOD'] ?? 'POST')),
|
||||
// 原始请求快照保留在扩展字段里,方便后续排查旧协议参数差异。
|
||||
'request_snapshot' => $this->normalizeRequestSnapshot($payload),
|
||||
'channel_callback_base_url' => (string) sys_config('site_url') . '/api/pay',
|
||||
];
|
||||
@@ -311,6 +423,15 @@ class EpayCompatService extends BaseService
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析提交支付方式。
|
||||
*
|
||||
* 空支付方式时,沿用当前系统默认启用支付方式;显式传值时必须是启用中的支付方式。
|
||||
*
|
||||
* @param string $typeCode 支付方式编码
|
||||
* @return PaymentType 支付方式模型
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function resolveSubmitPaymentType(string $typeCode): PaymentType
|
||||
{
|
||||
$typeCode = trim($typeCode);
|
||||
@@ -326,6 +447,14 @@ class EpayCompatService extends BaseService
|
||||
return $paymentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建旧版 MAPI 返回结构。
|
||||
*
|
||||
* 根据当前支付尝试结果,输出 payurl、qrcode 或 urlscheme 等旧协议字段。
|
||||
*
|
||||
* @param array $attempt 支付尝试结果
|
||||
* @return array<string, mixed> ePay 风格响应
|
||||
*/
|
||||
private function buildMapiResponse(array $attempt): array
|
||||
{
|
||||
/** @var PayOrder $payOrder */
|
||||
@@ -336,6 +465,7 @@ class EpayCompatService extends BaseService
|
||||
$response = ['code' => 1, 'msg' => '提交成功', 'trade_no' => $payNo];
|
||||
$type = (string) ($payParams['type'] ?? '');
|
||||
|
||||
// 不同插件返回的支付承载形态不同,这里按旧协议常见字段逐个兼容。
|
||||
if ($type === 'qrcode') {
|
||||
$qrcode = $this->stringifyValue($payParams['qrcode_url'] ?? $payParams['qrcode_data'] ?? '');
|
||||
if ($qrcode !== '') {
|
||||
@@ -364,6 +494,7 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
|
||||
if ($type === 'form' && $this->stringifyValue($payParams['html'] ?? '') !== '') {
|
||||
// 表单类承载本身会把页面内容交给插件,这里仍然只回传收银台入口。
|
||||
$response['payurl'] = $cashierUrl;
|
||||
return $response;
|
||||
}
|
||||
@@ -385,6 +516,13 @@ class EpayCompatService extends BaseService
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将当前支付单格式化为旧版订单查询结构。
|
||||
*
|
||||
* @param PayOrder $payOrder 支付订单
|
||||
* @param BizOrder|null $bizOrder 业务订单
|
||||
* @return array<string, mixed> 旧版订单结构
|
||||
*/
|
||||
private function formatEpayOrderRow(PayOrder $payOrder, ?BizOrder $bizOrder = null): array
|
||||
{
|
||||
$bizOrder ??= $this->bizOrderRepository->findByBizNo((string) $payOrder->biz_no);
|
||||
@@ -406,6 +544,15 @@ class EpayCompatService extends BaseService
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析支付订单上下文。
|
||||
*
|
||||
* 优先按 `trade_no` 查找,其次按 `out_trade_no` 回退,并校验订单归属当前商户。
|
||||
*
|
||||
* @param int $merchantId 商户ID
|
||||
* @param array $payload 请求载荷
|
||||
* @return array{pay_order: PayOrder, biz_order: BizOrder|null}|null 上下文
|
||||
*/
|
||||
private function resolvePayOrderContext(int $merchantId, array $payload): ?array
|
||||
{
|
||||
$payNo = trim((string) ($payload['trade_no'] ?? ''));
|
||||
@@ -414,6 +561,7 @@ class EpayCompatService extends BaseService
|
||||
$bizOrder = null;
|
||||
|
||||
if ($payNo !== '') {
|
||||
// 旧协议如果传了 trade_no,就优先按支付单号定位,命中率最高。
|
||||
$payOrder = $this->payOrderRepository->findByPayNo($payNo);
|
||||
if ($payOrder) {
|
||||
$bizOrder = $this->bizOrderRepository->findByBizNo((string) $payOrder->biz_no);
|
||||
@@ -421,12 +569,15 @@ class EpayCompatService extends BaseService
|
||||
}
|
||||
|
||||
if (!$payOrder && $merchantOrderNo !== '') {
|
||||
// 没有 trade_no 时,再按商户单号反查业务单和最新支付单。
|
||||
$bizOrder = $this->bizOrderRepository->findByMerchantAndOrderNo($merchantId, $merchantOrderNo);
|
||||
if ($bizOrder) {
|
||||
// 旧协议经常只传商户单号,这里拿业务单找到最新一笔支付单。
|
||||
$payOrder = $this->payOrderRepository->findLatestByBizNo((string) $bizOrder->biz_no);
|
||||
}
|
||||
}
|
||||
|
||||
// 旧协议有时会传到别家商户的单号,这里必须再次校验归属,避免跨商户读取。
|
||||
if (!$payOrder || (int) $payOrder->merchant_id !== $merchantId) {
|
||||
return null;
|
||||
}
|
||||
@@ -438,13 +589,26 @@ class EpayCompatService extends BaseService
|
||||
return ['pay_order' => $payOrder, 'biz_order' => $bizOrder];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付方式 ID 解析支付方式编码。
|
||||
*
|
||||
* @param int $payTypeId 支付方式ID
|
||||
* @return string 支付方式编码
|
||||
*/
|
||||
private function resolvePaymentTypeCode(int $payTypeId): string
|
||||
{
|
||||
return $this->paymentTypeService->resolveCodeById($payTypeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析商户结算类型。
|
||||
*
|
||||
* @param object $merchant 商户对象
|
||||
* @return int 结算类型编码
|
||||
*/
|
||||
private function resolveMerchantSettlementType(mixed $merchant): int
|
||||
{
|
||||
// 旧 Epay 协议里结算类型是约定好的整数,这里用账户信息做一个兼容性映射。
|
||||
$bankName = strtolower(trim((string) ($merchant->settlement_bank_name ?? '')));
|
||||
$accountName = strtolower(trim((string) ($merchant->settlement_account_name ?? '')));
|
||||
$accountNo = strtolower(trim((string) ($merchant->settlement_account_no ?? '')));
|
||||
@@ -468,6 +632,12 @@ class EpayCompatService extends BaseService
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将元金额转成分。
|
||||
*
|
||||
* @param string $money 金额字符串
|
||||
* @return int 金额分值,非法时返回 0
|
||||
*/
|
||||
private function parseMoneyToAmount(string $money): int
|
||||
{
|
||||
$money = trim($money);
|
||||
@@ -475,9 +645,19 @@ class EpayCompatService extends BaseService
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 旧协议金额按“元”传入,内部统一转成“分”处理。
|
||||
return (int) round(((float) $money) * 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析客户端 IP。
|
||||
*
|
||||
* 优先使用旧协议中的 `clientip`,缺省时回退到请求真实 IP。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @param Request $request 请求对象
|
||||
* @return string 客户端 IP
|
||||
*/
|
||||
private function resolveClientIp(array $payload, Request $request): string
|
||||
{
|
||||
$clientIp = trim((string) ($payload['clientip'] ?? ''));
|
||||
@@ -485,15 +665,29 @@ class EpayCompatService extends BaseService
|
||||
return $clientIp;
|
||||
}
|
||||
|
||||
// 旧请求没传 clientip 时,退回到框架识别的真实 IP。
|
||||
return trim((string) $request->getRealIp());
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化设备类型。
|
||||
*
|
||||
* @param string $device 设备编码
|
||||
* @return string 归一化后的设备编码
|
||||
*/
|
||||
private function normalizeDeviceCode(string $device): string
|
||||
{
|
||||
$device = strtolower(trim($device));
|
||||
// 没传设备类型时默认按 pc 处理,兼容旧接口的页面跳转场景。
|
||||
return $device !== '' ? $device : 'pc';
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化旧协议扩展参数。
|
||||
*
|
||||
* @param array|object|bool|float|int|string|null $value 扩展参数
|
||||
* @return array|string|null 归一化后的值
|
||||
*/
|
||||
private function normalizePayloadValue(mixed $value): mixed
|
||||
{
|
||||
if ($value === null) {
|
||||
@@ -512,30 +706,67 @@ class EpayCompatService extends BaseService
|
||||
return is_scalar($value) ? (string) $value : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成请求快照。
|
||||
*
|
||||
* 快照会移除敏感签名字段,便于落库排障。
|
||||
*
|
||||
* @param array $payload 请求载荷
|
||||
* @return array<string, mixed> 请求快照
|
||||
*/
|
||||
private function normalizeRequestSnapshot(array $payload): array
|
||||
{
|
||||
$snapshot = $payload;
|
||||
// 签名字段和内部 submit_mode 不参与快照展示,避免误导排障。
|
||||
unset($snapshot['sign'], $snapshot['key']);
|
||||
unset($snapshot['submit_mode']);
|
||||
return $snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建收银台跳转地址。
|
||||
*
|
||||
* @param string $payNo 支付单号
|
||||
* @return string 收银台 URL
|
||||
*/
|
||||
private function buildCashierUrl(string $payNo): string
|
||||
{
|
||||
return (string) sys_config('site_url') . '/pay/' . rawurlencode($payNo) . '/payment';
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化异常提示。
|
||||
*
|
||||
* @param Throwable $e 异常对象
|
||||
* @param string $fallback 默认文案
|
||||
* @return string 错误提示
|
||||
*/
|
||||
private function normalizeErrorMessage(Throwable $e, string $fallback): string
|
||||
{
|
||||
$message = trim((string) $e->getMessage());
|
||||
return $message !== '' ? $message : $fallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断插件返回的 success 标记。
|
||||
*
|
||||
* 如果插件未显式返回 `success`,则默认视为成功。
|
||||
*
|
||||
* @param array $pluginResult 插件结果
|
||||
* @return bool 插件是否通过
|
||||
*/
|
||||
private function isPluginSuccess(array $pluginResult): bool
|
||||
{
|
||||
return !array_key_exists('success', $pluginResult) || (bool) $pluginResult['success'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析退款渠道单号。
|
||||
*
|
||||
* @param array $pluginResult 插件结果
|
||||
* @param string $default 默认值
|
||||
* @return string 渠道退款单号
|
||||
*/
|
||||
private function resolveRefundChannelNo(array $pluginResult, string $default = ''): string
|
||||
{
|
||||
foreach (['chan_refund_no', 'refund_no', 'trade_no', 'out_request_no'] as $key) {
|
||||
@@ -550,6 +781,12 @@ class EpayCompatService extends BaseService
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将任意值规范化为字符串。
|
||||
*
|
||||
* @param array|object|bool|float|int|string|null $value 待转换值
|
||||
* @return string 规范化后的字符串
|
||||
*/
|
||||
private function stringifyValue(mixed $value): string
|
||||
{
|
||||
if ($value === null) {
|
||||
@@ -562,6 +799,7 @@ class EpayCompatService extends BaseService
|
||||
return (string) $value;
|
||||
}
|
||||
if (is_array($value) || is_object($value)) {
|
||||
// 复杂结构直接 JSON 化,保证旧协议回显时仍然可读。
|
||||
$json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
return $json !== false ? $json : '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user