chore: prepare production release package
This commit is contained in:
@@ -593,39 +593,92 @@ class SystemConfigsController
|
||||
throw new \RuntimeException('收钱吧订单有效分钟数需填写 1-43200 之间的整数');
|
||||
}
|
||||
|
||||
if (!$this->isPemContentOrReadablePath((string)$configValueMap['payment.merchant_private_key'])) {
|
||||
throw new \RuntimeException('商户 RSA 私钥需填写 PEM 内容,或填写服务器可读取的 PEM 文件路径');
|
||||
if (!$this->isPrivateKeyContentOrReadablePath((string)$configValueMap['payment.merchant_private_key'])) {
|
||||
throw new \RuntimeException('商户 RSA 私钥需填写可被 OpenSSL 解析的 PEM 内容,或填写服务器可读取的 PEM 文件路径');
|
||||
}
|
||||
if (!$this->isPublicKeyContentOrReadablePath((string)$configValueMap['payment.shouqianba_public_key'])) {
|
||||
throw new \RuntimeException('收钱吧 RSA 公钥需填写 PEM 内容、纯公钥文本,或填写服务器可读取的 PEM 文件路径');
|
||||
throw new \RuntimeException('收钱吧 RSA 公钥需填写可被 OpenSSL 解析的 PEM 内容、纯公钥文本,或填写服务器可读取的 PEM 文件路径');
|
||||
}
|
||||
}
|
||||
|
||||
private function isPrivateKeyContentOrReadablePath(string $value): bool
|
||||
{
|
||||
$content = $this->pemContentOrReadablePath($value);
|
||||
if ($content === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$key = openssl_pkey_get_private($content);
|
||||
$ok = $key !== false;
|
||||
$this->clearOpenSslErrors();
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
private function isPublicKeyContentOrReadablePath(string $value): bool
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($this->isPemContentOrReadablePath($value)) {
|
||||
$content = $this->pemContentOrReadablePath($value);
|
||||
if ($content !== '' && $this->canOpenPublicKey($content)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->looksLikeBase64KeyBody($value);
|
||||
if (!$this->looksLikeBase64KeyBody($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->canOpenPublicKey($this->wrapPemKey($value, 'PUBLIC KEY'));
|
||||
}
|
||||
|
||||
private function isPemContentOrReadablePath(string $value): bool
|
||||
private function pemContentOrReadablePath(string $value): string
|
||||
{
|
||||
$value = trim($value);
|
||||
if ($value === '') {
|
||||
return false;
|
||||
return '';
|
||||
}
|
||||
if (str_contains($value, '-----BEGIN')) {
|
||||
return true;
|
||||
return $this->normalizePemNewlines($value);
|
||||
}
|
||||
if (!is_file($value) || !is_readable($value)) {
|
||||
return false;
|
||||
return '';
|
||||
}
|
||||
|
||||
$content = file_get_contents($value);
|
||||
return is_string($content) && str_contains($content, '-----BEGIN');
|
||||
if (!is_string($content) || !str_contains($content, '-----BEGIN')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->normalizePemNewlines($content);
|
||||
}
|
||||
|
||||
private function canOpenPublicKey(string $content): bool
|
||||
{
|
||||
$key = openssl_pkey_get_public($content);
|
||||
$ok = $key !== false;
|
||||
$this->clearOpenSslErrors();
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
private function wrapPemKey(string $value, string $pemLabel): string
|
||||
{
|
||||
$body = preg_replace('/\s+/', '', trim($value)) ?: '';
|
||||
return sprintf(
|
||||
"-----BEGIN %s-----\n%s\n-----END %s-----",
|
||||
$pemLabel,
|
||||
rtrim(chunk_split($body, 64, "\n")),
|
||||
$pemLabel
|
||||
);
|
||||
}
|
||||
|
||||
private function normalizePemNewlines(string $value): string
|
||||
{
|
||||
return str_replace(["\\r\\n", "\\n", "\\r"], ["\n", "\n", "\r"], $value);
|
||||
}
|
||||
|
||||
private function clearOpenSslErrors(): void
|
||||
{
|
||||
while (openssl_error_string() !== false) {
|
||||
}
|
||||
}
|
||||
|
||||
private function looksLikeBase64KeyBody(string $value): bool
|
||||
|
||||
@@ -140,6 +140,46 @@ class AuthController
|
||||
}
|
||||
}
|
||||
|
||||
public function miniProgramExchange(Request $request)
|
||||
{
|
||||
$code = trim((string)$request->input('code', ''));
|
||||
if ($code === '') {
|
||||
return api_error('小程序登录 code 不能为空', 422);
|
||||
}
|
||||
|
||||
try {
|
||||
$payload = (new MiniProgramAuthService())->exchangeCode($code, $request);
|
||||
return api_success($payload, ($payload['status'] ?? '') === 'need_bind' ? '请绑定手机号' : '登录成功');
|
||||
} catch (\RuntimeException $e) {
|
||||
return api_error($e->getMessage(), 422);
|
||||
} catch (\Throwable $e) {
|
||||
return api_error('小程序授权登录失败', 500, [
|
||||
'detail' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function miniProgramBindMobile(Request $request)
|
||||
{
|
||||
$bindTicket = trim((string)$request->input('bind_ticket', ''));
|
||||
$mobile = trim((string)$request->input('mobile', ''));
|
||||
$code = trim((string)$request->input('code', ''));
|
||||
if ($bindTicket === '' || $mobile === '' || $code === '') {
|
||||
return api_error('小程序绑定凭证、手机号和验证码不能为空', 422);
|
||||
}
|
||||
|
||||
try {
|
||||
$payload = (new MiniProgramAuthService())->bindMobile($bindTicket, $mobile, $code, $request);
|
||||
return api_success($payload, '绑定成功');
|
||||
} catch (\RuntimeException $e) {
|
||||
return api_error($e->getMessage(), 422);
|
||||
} catch (\Throwable $e) {
|
||||
return api_error('小程序绑定手机号失败', 500, [
|
||||
'detail' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function me(Request $request)
|
||||
{
|
||||
$userInfo = (new AppAuthService())->current($request);
|
||||
|
||||
Reference in New Issue
Block a user