0.使用模拟数据进行充值和提现
1.优化提现接口/api/finance/withdrawCreate 2.优化充值接口/api/finance/depositCreate
This commit is contained in:
363
app/common/library/finance/MockPay.php
Normal file
363
app/common/library/finance/MockPay.php
Normal file
@@ -0,0 +1,363 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
|
||||
namespace app\common\library\finance;
|
||||
|
||||
use app\common\service\DepositOrderExpireService;
|
||||
|
||||
/**
|
||||
|
||||
* 模拟支付(无真实商户网关):用于开发/联调充值与提现审核。
|
||||
|
||||
*/
|
||||
|
||||
final class MockPay
|
||||
|
||||
{
|
||||
|
||||
public const CHANNEL_CODE = 'mock';
|
||||
|
||||
|
||||
|
||||
/** 待审核(用户已在模拟页确认支付,等待后台审核) */
|
||||
|
||||
public const DEPOSIT_STATUS_PENDING_REVIEW = 3;
|
||||
|
||||
|
||||
|
||||
public static function isEnabled(): bool
|
||||
|
||||
{
|
||||
|
||||
$raw = getenv('FINANCE_MOCK_PAY_ENABLED');
|
||||
|
||||
if (is_string($raw) && trim($raw) !== '') {
|
||||
|
||||
$norm = strtolower(trim($raw));
|
||||
|
||||
if (in_array($norm, ['0', 'false', 'no', 'off'], true)) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
if (in_array($norm, ['1', 'true', 'yes', 'on'], true)) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$cfg = config('app.finance_mock_pay_enabled', null);
|
||||
|
||||
if ($cfg === true) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if ($cfg === false) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$debugRaw = getenv('APP_DEBUG');
|
||||
|
||||
if (is_string($debugRaw) && trim($debugRaw) !== '') {
|
||||
|
||||
return in_array(strtolower(trim($debugRaw)), ['1', 'true', 'yes', 'on'], true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 提现审核后是否走模拟出金(不调用 DDPay)。
|
||||
* - pay_channel=mock:始终模拟;
|
||||
* - FINANCE_MOCK_PAY_ENABLED 开启:ddpay/空 一律模拟(审核通过即成功);
|
||||
* - 未开启 mock 且未配置 DDPay:ddpay/空 也模拟,避免误调网关。
|
||||
*/
|
||||
public static function shouldSimulateWithdrawPayout(string $payChannel): bool
|
||||
{
|
||||
$ch = strtolower(trim($payChannel));
|
||||
if ($ch === self::CHANNEL_CODE) {
|
||||
return true;
|
||||
}
|
||||
if ($ch !== '' && $ch !== 'ddpay') {
|
||||
return false;
|
||||
}
|
||||
if (self::isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !DDPayGateway::isConfigured();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* 计算链接过期时间与签名(防猜单号)
|
||||
|
||||
*
|
||||
|
||||
* @return array{expire_at: int, sign: string}
|
||||
|
||||
*/
|
||||
|
||||
public static function buildDepositLinkAuth(string $orderNo, int $createTime): array
|
||||
|
||||
{
|
||||
|
||||
$expireAt = $createTime + DepositOrderExpireService::pendingExpireSeconds();
|
||||
|
||||
|
||||
|
||||
return [
|
||||
|
||||
'expire_at' => $expireAt,
|
||||
|
||||
'sign' => self::signDepositLink($orderNo, $expireAt),
|
||||
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function signDepositLink(string $orderNo, int $expireAt): string
|
||||
|
||||
{
|
||||
|
||||
$params = [
|
||||
|
||||
'expire_at' => strval($expireAt),
|
||||
|
||||
'order_no' => $orderNo,
|
||||
|
||||
'secret' => self::linkSecret(),
|
||||
|
||||
];
|
||||
|
||||
ksort($params);
|
||||
|
||||
$pairs = [];
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
|
||||
$pairs[] = $key . '=' . $value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return strtoupper(md5(implode('&', $pairs)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function verifyDepositLink(string $orderNo, int $expireAt, string $sign): bool
|
||||
|
||||
{
|
||||
|
||||
$signNorm = strtoupper(trim($sign));
|
||||
|
||||
if ($signNorm === '' || $orderNo === '' || $expireAt <= 0) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return hash_equals(self::signDepositLink($orderNo, $expireAt), $signNorm);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* 前端静态收银台 URL(优先于服务端内联页)
|
||||
|
||||
*
|
||||
|
||||
* @param string $amountDisplay 2 位小数字符串,供页面展示
|
||||
|
||||
* @param string $bonusDisplay 2 位小数字符串
|
||||
|
||||
*/
|
||||
|
||||
public static function depositPageUrl(
|
||||
|
||||
string $orderNo,
|
||||
|
||||
string $publicOrigin,
|
||||
|
||||
int $expireAt,
|
||||
|
||||
string $sign,
|
||||
|
||||
string $amountDisplay = '',
|
||||
|
||||
string $bonusDisplay = ''
|
||||
|
||||
): string {
|
||||
|
||||
$htmlBase = self::resolveHtmlBase($publicOrigin);
|
||||
|
||||
$apiBase = rtrim($publicOrigin, '/');
|
||||
|
||||
|
||||
|
||||
$query = [
|
||||
|
||||
'order_no' => $orderNo,
|
||||
|
||||
'expire_at' => strval($expireAt),
|
||||
|
||||
'sign' => $sign,
|
||||
|
||||
'api_base' => $apiBase,
|
||||
|
||||
];
|
||||
|
||||
if ($amountDisplay !== '') {
|
||||
|
||||
$query['amount'] = $amountDisplay;
|
||||
|
||||
}
|
||||
|
||||
if ($bonusDisplay !== '') {
|
||||
|
||||
$query['bonus'] = $bonusDisplay;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $htmlBase . '/mock-deposit.html?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* 模拟页内确认支付接口(无需 auth-token;须携带 sign + expire_at)
|
||||
|
||||
*/
|
||||
|
||||
public static function depositConfirmUrl(string $orderNo, string $publicOrigin, int $expireAt, string $sign): string
|
||||
|
||||
{
|
||||
|
||||
$base = rtrim($publicOrigin, '/');
|
||||
|
||||
$query = http_build_query([
|
||||
|
||||
'order_no' => $orderNo,
|
||||
|
||||
'expire_at' => strval($expireAt),
|
||||
|
||||
'sign' => $sign,
|
||||
|
||||
], '', '&', PHP_QUERY_RFC3986);
|
||||
|
||||
|
||||
|
||||
return $base . '/api/finance/mockDepositConfirm?' . $query;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* 解析前端静态页根地址:MOCK_DEPOSIT_HTML_BASE > DDPAY_PUBLIC_BASE_URL > API 公网根
|
||||
|
||||
*/
|
||||
|
||||
public static function resolveHtmlBase(string $publicOrigin): string
|
||||
|
||||
{
|
||||
|
||||
$raw = getenv('MOCK_DEPOSIT_HTML_BASE');
|
||||
|
||||
if (is_string($raw) && trim($raw) !== '') {
|
||||
|
||||
return rtrim(trim($raw), '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$ddpayPublic = getenv('DDPAY_PUBLIC_BASE_URL');
|
||||
|
||||
if (is_string($ddpayPublic) && trim($ddpayPublic) !== '') {
|
||||
|
||||
return rtrim(trim($ddpayPublic), '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$cfg = config('app.ddpay_public_base_url', '');
|
||||
|
||||
if (is_string($cfg) && trim($cfg) !== '') {
|
||||
|
||||
return rtrim(trim($cfg), '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return rtrim($publicOrigin, '/');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static function linkSecret(): string
|
||||
|
||||
{
|
||||
|
||||
$raw = getenv('FINANCE_MOCK_PAY_LINK_SECRET');
|
||||
|
||||
if (is_string($raw) && trim($raw) !== '') {
|
||||
|
||||
return trim($raw);
|
||||
|
||||
}
|
||||
|
||||
$auth = getenv('AUTH_TOKEN_SECRET');
|
||||
|
||||
if (is_string($auth) && trim($auth) !== '') {
|
||||
|
||||
return trim($auth);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return 'mock-deposit-link-dev-secret';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user