CoinPay.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <?php
  2. namespace App\Services;
  3. use App\Util;
  4. class CoinPay
  5. {
  6. protected $config;
  7. protected $key;
  8. protected $appId;
  9. protected $apiUrl;
  10. protected $version;
  11. public function __construct(string $configKey = 'CoinPay')
  12. {
  13. $payConfig = new PayConfig();
  14. $this->config = $payConfig->getConfig($configKey);
  15. $this->key = $this->config['key'] ?? '';
  16. $this->appId = $this->config['appId'] ?? '';
  17. $this->apiUrl = rtrim($this->config['apiUrl'] ?? '', '/');
  18. $this->version = $this->config['version'] ?? 'v1';
  19. }
  20. public function getConfig(): array
  21. {
  22. return $this->config;
  23. }
  24. public function sign(array $params): array
  25. {
  26. if (!isset($params['appId']) && $this->appId) {
  27. $params['appId'] = $this->appId;
  28. }
  29. $params['sign'] = $this->generateSign($params);
  30. return $params;
  31. }
  32. public function verify(array $params): bool
  33. {
  34. if (!isset($params['sign'])) {
  35. return false;
  36. }
  37. $received = strtolower($params['sign']);
  38. unset($params['sign']);
  39. if (!isset($params['appId']) && $this->appId) {
  40. $params['appId'] = $this->appId;
  41. }
  42. return $received === $this->generateSign($params);
  43. }
  44. public function post(string $path, array $payload)
  45. {
  46. $url = $this->apiUrl . $path;
  47. $headers = [
  48. 'Content-Type: application/json; charset=UTF-8',
  49. 'version: ' . $this->version,
  50. 'appId: ' . $this->appId,
  51. ];
  52. $body = json_encode($payload, JSON_UNESCAPED_UNICODE);
  53. $ch = curl_init();
  54. curl_setopt($ch, CURLOPT_URL, $url);
  55. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  56. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  57. curl_setopt($ch, CURLOPT_POST, 1);
  58. curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
  59. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  60. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  61. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  62. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  63. $result = curl_exec($ch);
  64. if (curl_errno($ch)) {
  65. Util::WriteLog('CoinPay_error', 'CURL Error: ' . curl_error($ch));
  66. }
  67. curl_close($ch);
  68. return $result;
  69. }
  70. protected function generateSign(array $params): string
  71. {
  72. $filtered = [];
  73. foreach ($params as $key => $value) {
  74. if ($key === 'sign') {
  75. continue;
  76. }
  77. if ($value === null || $value === '') {
  78. continue;
  79. }
  80. if (is_array($value)) {
  81. $value = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
  82. }
  83. $filtered[$key] = $value;
  84. }
  85. ksort($filtered);
  86. $segments = [];
  87. foreach ($filtered as $key => $value) {
  88. $segments[] = $key . '=' . $value;
  89. }
  90. $segments[] = 'key=' . $this->key;
  91. $string = implode('&', $segments);
  92. return strtolower(hash('sha256', $string));
  93. }
  94. }