chengkun
2025-09-09 1ff9e27b020822168a95edd83be567e7153837f3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php
namespace DoubleBreak\Spapi;
 
class Client {
 
  use HttpClientFactoryTrait;
 
  protected $credentials;
  protected $config;
  protected $signer;
  protected $lastHttpResponse = null;
  public function __construct(array $credentials = [], array $config = [])
  {
    $this->credentials = $credentials;
    $this->config = $config;
    $this->signer = new Signer(); //Should be injected :(
  }
 
 
  private function normalizeHeaders($headers)
  {
    return $result = array_combine(
       array_map(function($header) { return strtolower($header); }, array_keys($headers)),
       $headers
    );
 
  }
 
  private function headerValue($header)
  {
      return \GuzzleHttp\Psr7\Header::parse($header)[0];
  }
 
 
  private function prepareRequestOptions($uri, $requestOptions)
  {
      $requestOptions['headers'] = $requestOptions['headers'] ?? [];
      $requestOptions['headers']['accept'] = 'application/json';
      $requestOptions['headers'] = $this->normalizeHeaders($requestOptions['headers']);
 
 
      //Prepare for signing
      $signOptions = [
        'service' => 'execute-api',
        'access_token' => $this->credentials['access_token'],
        'access_key' => $this->credentials['sts_credentials']['access_key'],
        'secret_key' =>  $this->credentials['sts_credentials']['secret_key'],
        'security_token' =>  $this->credentials['sts_credentials']['session_token'],
        'region' =>  $this->config['region'] ?? null,
        'host' => $this->config['host'],
        'uri' =>  $uri,
        'method' => $requestOptions['method']
      ];
 
      if (isset($requestOptions['query'])) {
        $query = $requestOptions['query'];
        ksort($query);
        $signOptions['query_string'] =  \GuzzleHttp\Psr7\build_query($query);
      }
 
      if (isset($requestOptions['form_params'])) {
        ksort($requestOptions['form_params']);
        $signOptions['payload'] = \GuzzleHttp\Psr7\build_query($requestOptions['form_params']);
      }
 
      if (isset($requestOptions['json'])) {
        ksort($requestOptions['json']);
        $signOptions['payload'] = json_encode($requestOptions['json']);
      }
 
      //Sign
      $requestOptions = $this->signer->sign($requestOptions, $signOptions);
 
      return $requestOptions;
  }
 
  public function send($uri, $requestOptions = [])
  {
 
    $requestOptions = $this->prepareRequestOptions($uri, $requestOptions);
    $client = $this->createHttpClient([
      'base_uri' => 'https://' . $this->config['host'],
      'timeout'  => 3.0,
    ]);
 
    try {
      $this->lastHttpResponse = null;
      $method = $requestOptions['method'];
      unset($requestOptions['method']);
      $response = $client->request($method, $uri, $requestOptions);
      $this->lastHttpResponse = $response;
      return json_decode($response->getBody(), true);
    } catch (\GuzzleHttp\Exception\ClientException $e) {
      $this->lastHttpResponse = $e->getResponse();
      throw $e;
    }
 
  }
 
  public function sendAsync($uri, $requestOptions)
  {
      $requestOptions = $this->prepareRequestOptions($uri, $requestOptions);
      $client = $this->createHttpClient([
        'base_uri' => 'https://' . $this->config['host'],
        'timeout'  => 3.0,
      ]);
      $method = $requestOptions['method'];
      unset($requestOptions['method']);
      return  $client->requestAsync($method, $uri, $requestOptions);
  }
 
  public function getLastHttpResponse()
  {
    return $this->lastHttpResponse;
  }
 
}