1、合作商余额查询

2、分油账户司机可用额度
This commit is contained in:
2026-10-08 23:12:33 +08:00
parent ae94c1dc00
commit 45452c1799
32 changed files with 2024 additions and 6 deletions
+152
View File
@@ -0,0 +1,152 @@
<?php
// +----------------------------------------------------------------------
// | RSA 密钥自检 —— 排查下游报 errCode=0007「请求参数解析异常」(CLI)
// +----------------------------------------------------------------------
// | 0007 的实际含义是:我方用【平台私钥】解不开下游加密的 AES 密钥。
// | 报错里的「PEM routines:no start line」是 OpenSSL 错误队列的残留信息,
// | 具有误导性,真正原因几乎都是:下游加密时用的公钥 ≠ 我方平台私钥对应的公钥。
// |
// | 用法(站点根目录执行):
// | php deploy/rsa_check.php 自检密钥对 + 打印要发给下游的公钥
// | php deploy/rsa_check.php <appKey> 再检查该合作商的公钥(用于验签其请求)
// | php deploy/rsa_check.php <appKey> "<key密文>" 用请求里的 key 字段实测能否解开
// |
// | 其中「key密文」是下游请求体 {"key":"...","data":"..."} 里的 key 原值。
// +----------------------------------------------------------------------
declare (strict_types=1);
if (PHP_SAPI !== 'cli') {
http_response_code(403);
exit('仅限命令行执行');
}
$root = dirname(__DIR__);
$appKey = $argv[1] ?? '';
$encKey = $argv[2] ?? '';
function line(): void
{
echo str_repeat('-', 62) . "\n";
}
/** 取密钥指纹,便于和对方核对是不是同一把 */
function fingerprint($keyRes): string
{
$d = openssl_pkey_get_details($keyRes);
return isset($d['rsa']['n']) ? strtoupper(substr(md5($d['rsa']['n']), 0, 16)) : '(取不到)';
}
// ================================================================
// 1. 平台密钥对
// ================================================================
echo "【1】平台密钥对\n";
line();
$privPath = $root . '/rsa/private_key.pem';
$pubPath = $root . '/rsa/public_key.pem';
foreach ([$privPath, $pubPath] as $p) {
printf(" %-28s %s\n", basename($p), is_file($p) ? '存在(' . filesize($p) . ' 字节)' : '❌ 不存在');
}
if (!is_file($privPath) || !is_file($pubPath)) {
exit("\n❌ 密钥文件缺失,下游所有请求都会失败。\n");
}
$priv = openssl_pkey_get_private(file_get_contents($privPath));
$pub = openssl_pkey_get_public(file_get_contents($pubPath));
printf(" 平台私钥加载%s\n", $priv ? '成功' : '❌ 失败:' . openssl_error_string());
printf(" 平台公钥加载%s\n", $pub ? '成功' : '❌ 失败:' . openssl_error_string());
if (!$priv || !$pub) {
exit("\n❌ 密钥文件格式不对,请检查是否为完整 PEM(含 BEGIN/END 行)。\n");
}
$dPriv = openssl_pkey_get_details($priv);
$dPub = openssl_pkey_get_details($pub);
printf(" 位数:私钥 %d / 公钥 %d\n", $dPriv['bits'], $dPub['bits']);
$pairOk = $dPriv['key'] === $dPub['key'];
printf(" 两者是否同一对:%s\n", $pairOk ? '是' : '❌ 否(公私钥不配套,必须换成同一对)');
// 实测闭环
$aes = openssl_random_pseudo_bytes(32);
openssl_public_encrypt($aes, $enc, $pub, OPENSSL_PKCS1_PADDING);
$loopOk = openssl_private_decrypt($enc, $dec, $priv, OPENSSL_PKCS1_PADDING) && $dec === $aes;
printf(" 加密→解密闭环:%s\n", $loopOk ? '通过' : '❌ 失败');
printf(" 平台公钥指纹:%s\n", fingerprint($pub));
// ================================================================
// 2. 发给下游的公钥(他们必须用这一把加密 AES 密钥)
// ================================================================
echo "\n【2】请把下面这把【平台公钥】发给下游,让他们核对\n";
line();
echo trim(file_get_contents($pubPath)) . "\n\n";
echo "一行 base64(Java 可直接用):\n";
echo preg_replace('/\s+/', '', str_replace(['-----BEGIN PUBLIC KEY-----', '-----END PUBLIC KEY-----'], '', file_get_contents($pubPath))) . "\n";
// ================================================================
// 3. 合作商公钥(我方用它验签下游请求)
// ================================================================
if ($appKey !== '') {
echo "\n【3】合作商 {$appKey}\n";
line();
try {
$ini = @parse_ini_file($root . '/.env', true, INI_SCANNER_RAW) ?: [];
$db = $ini['DATABASE'] ?? [];
$pdo = new PDO(
'mysql:host=' . ($db['HOSTNAME'] ?? '127.0.0.1') . ';port=' . ($db['HOSTPORT'] ?? '3306')
. ';dbname=' . ($db['DATABASE'] ?? 'oil') . ';charset=' . ($db['CHARSET'] ?? 'utf8'),
$db['USERNAME'] ?? 'root', $db['PASSWORD'] ?? '',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);
$st = $pdo->prepare('SELECT partners_id, name, orgNo, appKey, publicKey, privateKey FROM yoshop_partners WHERE appKey = ? LIMIT 1');
$st->execute([$appKey]);
$p = $st->fetch();
if (!$p) {
echo " ❌ 未找到该 appKey 的合作商\n";
} else {
printf(" 合作商:%s(partners_id=%s,orgNo=%s)\n", $p['name'], $p['partners_id'], $p['orgNo']);
$ppub = openssl_pkey_get_public((string) $p['publicKey']);
printf(" 合作商公钥:%s%s\n", $ppub ? '可加载' : '❌ 无法加载:' . openssl_error_string(),
$ppub ? ' 指纹 ' . fingerprint($ppub) : '');
echo " 用途:我方用它验签下游请求。下游必须用与之配套的私钥加签,否则报 0006。\n";
if (!empty($p['privateKey'])) {
$ppriv = openssl_pkey_get_private((string) $p['privateKey']);
if ($ppub && $ppriv) {
$dd = openssl_pkey_get_details($ppriv);
printf(" 库里另存的合作商私钥与其公钥是否配套:%s\n",
$dd['key'] === openssl_pkey_get_details($ppub)['key'] ? '是' : '❌ 否');
echo " (这把私钥是发给下游用的,请确认下游手里就是它)\n";
}
}
}
} catch (Throwable $e) {
echo ' 查询失败:' . $e->getMessage() . "\n";
}
}
// ================================================================
// 4. 用真实请求里的 key 密文实测
// ================================================================
if ($encKey !== '') {
echo "\n【4】实测解密下游请求里的 key\n";
line();
$raw = base64_decode($encKey, true);
if ($raw === false) {
echo " ❌ 不是合法 base64\n";
} else {
printf(" 密文长度:%d 字节(%d 位密钥应为 %d 字节)\n", strlen($raw), $dPriv['bits'], $dPriv['bits'] / 8);
while (openssl_error_string() !== false) {
// 先清空 OpenSSL 错误队列,避免读到别处残留的 PEM 报错
}
$ok = openssl_private_decrypt($raw, $out, $priv, OPENSSL_PKCS1_PADDING);
if ($ok) {
printf(" ✅ 解密成功,AES 密钥长度 %d 字节(应为 32)\n", strlen($out));
echo " 说明密钥是配套的,0007 的原因在别处,请把完整请求发来再看。\n";
} else {
echo " ❌ 解密失败:" . (openssl_error_string() ?: '无附加信息') . "\n";
echo " 结论:下游加密用的公钥,与我方平台私钥不是一对。\n";
echo " 让下游换成【2】里打印的那把平台公钥即可。\n";
}
}
}
echo "\n";