check_mini_sms.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. <?php
  2. declare(strict_types=1);
  3. /** Read-only SMS checks; --gateway queries the account quota without sending a message. */
  4. require dirname(__DIR__) . '/vendor/autoload.php';
  5. \Dotenv\Dotenv::createUnsafeMutable(dirname(__DIR__))->load();
  6. \support\App::loadAllConfig(['route']);
  7. use app\miniapi\auth\SmsCode;
  8. use app\miniapi\model\MiniSmsCode;
  9. use app\miniapi\model\MiniUser;
  10. $endpoint = (string) config('mini_api.sms_endpoint', '');
  11. $host = parse_url($endpoint, PHP_URL_HOST);
  12. $signature = trim((string) config('mini_api.sms_signature', ''));
  13. $checks = [
  14. 'curl' => extension_loaded('curl'),
  15. 'mbstring' => extension_loaded('mbstring'),
  16. 'pdo_mysql' => extension_loaded('pdo_mysql'),
  17. 'sms_enabled_with_credentials' => SmsCode::enabled(),
  18. 'signature_configured' => $signature !== '',
  19. 'https_endpoint' => parse_url($endpoint, PHP_URL_SCHEME) === 'https'
  20. && in_array($host, ['api.smsbao.com', 'www.smsbao.com'], true)
  21. && parse_url($endpoint, PHP_URL_PATH) === '/sms'
  22. && parse_url($endpoint, PHP_URL_QUERY) === null,
  23. ];
  24. $report = [
  25. 'php_binary' => PHP_BINARY,
  26. 'php_ini' => php_ini_loaded_file(),
  27. 'additional_ini' => php_ini_scanned_files() ?: null,
  28. 'curl_cainfo' => ini_get('curl.cainfo') ?: null,
  29. 'openssl_cafile' => ini_get('openssl.cafile') ?: null,
  30. 'sms_host' => $host,
  31. 'signature' => $signature !== '' ? $signature : null,
  32. ];
  33. foreach ([
  34. 'mini_user_phone_schema' => [new MiniUser(), ['id', 'phone', 'status']],
  35. 'sms_code_schema' => [new MiniSmsCode(), ['id', 'phone', 'purpose', 'code_hash', 'attempts', 'expires_at', 'consumed_at', 'request_ip', 'created_at']],
  36. ] as $name => [$model, $columns]) {
  37. try {
  38. $model->newQuery()->select($columns)->limit(1)->get();
  39. $checks[$name] = true;
  40. } catch (\Throwable $exception) {
  41. $checks[$name] = false;
  42. $report['database_errors'][$name] = [
  43. 'type' => get_class($exception),
  44. 'code' => $exception->getCode(),
  45. ];
  46. }
  47. }
  48. if (in_array('--gateway', $argv, true)) {
  49. if (!$checks['curl'] || !$checks['sms_enabled_with_credentials'] || !$checks['https_endpoint']) {
  50. $checks['gateway'] = false;
  51. $report['gateway'] = ['skipped' => 'Fix the extension, account or endpoint checks first.'];
  52. } else {
  53. $username = (string) config('mini_api.sms_user', '');
  54. $credential = (string) config('mini_api.sms_password', '');
  55. $url = 'https://' . $host . '/query?' . http_build_query(['u' => $username, 'p' => $credential]);
  56. $curl = curl_init($url);
  57. curl_setopt_array($curl, [
  58. CURLOPT_RETURNTRANSFER => true,
  59. CURLOPT_CONNECTTIMEOUT => 5,
  60. CURLOPT_TIMEOUT => 10,
  61. CURLOPT_SSL_VERIFYPEER => true,
  62. CURLOPT_SSL_VERIFYHOST => 2,
  63. CURLOPT_FOLLOWLOCATION => false,
  64. ]);
  65. $raw = curl_exec($curl);
  66. $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
  67. $errorNumber = curl_errno($curl);
  68. $error = curl_error($curl);
  69. curl_close($curl);
  70. $lines = $raw === false ? [] : preg_split('/\r?\n/', trim($raw));
  71. $status = $lines[0] ?? '';
  72. $checks['gateway'] = $httpStatus === 200 && $status === '0';
  73. $report['gateway'] = [
  74. 'http_status' => $httpStatus,
  75. 'curl_errno' => $errorNumber,
  76. 'provider_status' => preg_match('/^-?\d+$/D', $status) ? $status : null,
  77. ];
  78. if ($error !== '') {
  79. $report['gateway']['transport_error'] = str_replace(
  80. [$url, rawurlencode($credential), $credential, $username],
  81. '[redacted]',
  82. $error
  83. );
  84. }
  85. if ($checks['gateway'] && preg_match('/^\d+,\d+$/D', $lines[1] ?? '')) {
  86. [$sent, $remaining] = explode(',', $lines[1]);
  87. $report['gateway']['remaining_sms'] = (int) $remaining;
  88. }
  89. }
  90. }
  91. $report['checks'] = $checks;
  92. $report['ok'] = !in_array(false, $checks, true);
  93. echo json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
  94. exit($report['ok'] ? 0 : 1);