Compare commits
2 Commits
438580d72c
...
907f7cb315
| Author | SHA1 | Date | |
|---|---|---|---|
| 907f7cb315 | |||
| 713170308b |
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace app\support;
|
||||
|
||||
use support\Log;
|
||||
use support\Response;
|
||||
use Webman\Http\Request as WebmanRequest;
|
||||
|
||||
@@ -93,6 +94,20 @@ abstract class BaseController
|
||||
$statusCode = $header['statusCode'] ?? 200;
|
||||
unset($header['statusCode']);
|
||||
|
||||
if ($code !== 1) {
|
||||
$req = $this->request;
|
||||
$method = $req ? $req->method() : '';
|
||||
$path = $req ? trim($req->path(), '/') : '';
|
||||
$ip = $req ? strval($req->getRealIp()) : '';
|
||||
$msgForLog = $msg;
|
||||
if (function_exists('mb_strlen') && function_exists('mb_substr') && mb_strlen($msgForLog) > 2000) {
|
||||
$msgForLog = mb_substr($msgForLog, 0, 2000) . '...';
|
||||
} elseif (strlen($msgForLog) > 2000) {
|
||||
$msgForLog = substr($msgForLog, 0, 2000) . '...';
|
||||
}
|
||||
Log::error('[API] ' . $method . ' /' . $path . ' | business_code=' . strval($code) . ' http=' . strval($statusCode) . ' ip=' . $ip . ' msg=' . $msgForLog);
|
||||
}
|
||||
|
||||
$headers = array_merge(['Content-Type' => 'application/json'], $header);
|
||||
$options = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
|
||||
if (defined('JSON_INVALID_UTF8_SUBSTITUTE')) {
|
||||
|
||||
131
scripts/playx-verify-token-callback-test.php
Normal file
131
scripts/playx-verify-token-callback-test.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* 命令行模拟商城服务端调用 PLAYX_TOKEN_VERIFY_URL(回调 verify-token)。
|
||||
*
|
||||
* 用法(在项目根目录执行):
|
||||
* php scripts/playx-verify-token-callback-test.php "<playx_token>"
|
||||
*
|
||||
* 可选环境变量(未设置则从项目根 .env 读取):
|
||||
* PLAYX_TOKEN_VERIFY_URL 默认 https://callback-mallsys.superior3.net/callback/api/mallsys/plx/auth/verify-token
|
||||
* PLAYX_ANGPOW_IMPORT_AUTH_KEY 与 angpow-imports 相同的 HMAC 密钥
|
||||
*/
|
||||
|
||||
$root = dirname(__DIR__);
|
||||
|
||||
function loadDotEnv(string $path): void
|
||||
{
|
||||
if (!is_file($path)) {
|
||||
return;
|
||||
}
|
||||
foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [] as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === '' || str_starts_with($line, '#')) {
|
||||
continue;
|
||||
}
|
||||
if (!str_contains($line, '=')) {
|
||||
continue;
|
||||
}
|
||||
$pos = strpos($line, '=');
|
||||
$name = trim(substr($line, 0, $pos));
|
||||
$value = trim(substr($line, $pos + 1));
|
||||
if ($name !== '') {
|
||||
$_ENV[$name] = $value;
|
||||
putenv($name . '=' . $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resolveKeyBytes(string $authKey): string
|
||||
{
|
||||
$maybeBase64 = base64_decode($authKey, true);
|
||||
if (is_string($maybeBase64) && $maybeBase64 !== '') {
|
||||
return $maybeBase64;
|
||||
}
|
||||
$isHex = ctype_xdigit($authKey) && (strlen($authKey) % 2 === 0);
|
||||
if ($isHex) {
|
||||
$hex = hex2bin($authKey);
|
||||
if (is_string($hex) && $hex !== '') {
|
||||
return $hex;
|
||||
}
|
||||
}
|
||||
|
||||
return $authKey;
|
||||
}
|
||||
|
||||
function buildSignature(string $input, string $authKey): string
|
||||
{
|
||||
$raw = hash_hmac('sha1', $input, resolveKeyBytes($authKey), true);
|
||||
|
||||
return base64_encode($raw);
|
||||
}
|
||||
|
||||
loadDotEnv($root . DIRECTORY_SEPARATOR . '.env');
|
||||
|
||||
$token = $argv[1] ?? '';
|
||||
if ($token === '') {
|
||||
fwrite(STDERR, "用法: php scripts/playx-verify-token-callback-test.php \"<playx_token>\"\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$url = strval($_ENV['PLAYX_TOKEN_VERIFY_URL'] ?? getenv('PLAYX_TOKEN_VERIFY_URL') ?: '');
|
||||
if ($url === '') {
|
||||
$url = 'https://callback-mallsys.superior3.net/callback/api/mallsys/plx/auth/verify-token';
|
||||
}
|
||||
|
||||
$authKey = strval($_ENV['PLAYX_ANGPOW_IMPORT_AUTH_KEY'] ?? getenv('PLAYX_ANGPOW_IMPORT_AUTH_KEY') ?: '');
|
||||
if ($authKey === '') {
|
||||
fwrite(STDERR, "缺少 PLAYX_ANGPOW_IMPORT_AUTH_KEY(请在 .env 配置或导出环境变量)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$requestId = 'mall_cli_' . uniqid();
|
||||
$canonical = 'request_id=' . $requestId . '&token=' . $token;
|
||||
$signature = buildSignature($canonical, $authKey);
|
||||
|
||||
$payload = json_encode([
|
||||
'request_id' => $requestId,
|
||||
'token' => $token,
|
||||
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if ($payload === false) {
|
||||
fwrite(STDERR, "JSON 编码失败\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$escapedPayload = str_replace("'", "'\\''", $payload);
|
||||
$escapedSig = str_replace("'", "'\\''", $signature);
|
||||
|
||||
echo "--- 等价 curl(Linux / macOS / Git Bash)---\n";
|
||||
echo "curl -sS -X POST '" . $url . "' \\\n";
|
||||
echo " -H 'Content-Type: application/json' \\\n";
|
||||
echo " -H 'X-Request-Signature: " . $signature . "' \\\n";
|
||||
echo " -d '" . $payload . "'\n\n";
|
||||
|
||||
echo "--- 本机直接请求(PHP stream)---\n";
|
||||
echo "request_id={$requestId}\n";
|
||||
echo "canonical={$canonical}\n\n";
|
||||
|
||||
$body = $payload;
|
||||
$ctx = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'header' => "Content-Type: application/json\r\nX-Request-Signature: {$signature}\r\n",
|
||||
'content' => $body,
|
||||
'timeout' => 15,
|
||||
],
|
||||
'ssl' => [
|
||||
'verify_peer' => true,
|
||||
'verify_peer_name' => true,
|
||||
],
|
||||
]);
|
||||
|
||||
$result = @file_get_contents($url, false, $ctx);
|
||||
if ($result === false) {
|
||||
$err = error_get_last();
|
||||
fwrite(STDERR, "请求失败: " . ($err['message'] ?? 'unknown') . "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo $result . "\n";
|
||||
Reference in New Issue
Block a user