Issues (13)

src/Service/AlmaApi.php (4 issues)

1
<?php
2
3
namespace App\Service;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\GuzzleException;
7
use Psr\Log\LoggerInterface;
8
use SimpleXMLElement;
9
10
/**
11
 * Provides functionality for accessing the Alma API.
12
 */
13
class AlmaApi
14
{
15
    private $logger;
16
17
    public function __construct(LoggerInterface $logger)
18
    {
19
        $this->logger = $logger;
20
    }
21
22
    /**
23
     * Wrapper for requests to Alma API
24
     *
25
     * @param $urlPath
26
     * @param $method
27
     * @param $requestParams
28
     * @param $templateParamNames
29
     * @param $templateParamValues
30
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
31
     * @throws GuzzleException
32
     */
33
    protected function executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues)
34
    {
35
        $client = new Client(['base_uri' => getenv('API_URL')]);
36
37
        $url = str_replace($templateParamNames, $templateParamValues, $urlPath);
38
        $defaultRequestParams = [
39
            'headers' => [
40
                'Authorization' => 'apikey ' . getenv('API_KEY'),
41
            ]
42
        ];
43
44
        try {
45
            $response = $client->request($method, $url, array_merge_recursive($requestParams, $defaultRequestParams));
46
        } catch (\Exception $e) {
47
            $emergency = true;
48
            $emergencyClientStatusCodes = ['404', '403', '401'];
49
            if ($e->hasResponse()) {
0 ignored issues
show
The method hasResponse() does not exist on Exception. It seems like you code against a sub-type of Exception such as GuzzleHttp\Exception\RequestException. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

49
            if ($e->/** @scrutinizer ignore-call */ hasResponse()) {
Loading history...
50
                $response = $e->getResponse();
0 ignored issues
show
The method getResponse() does not exist on Exception. It seems like you code against a sub-type of Exception such as GuzzleHttp\Exception\RequestException. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

50
                /** @scrutinizer ignore-call */ 
51
                $response = $e->getResponse();
Loading history...
51
                $statusCode = $response->getStatusCode();
52
                // 500 errors are always considered and emergency
53
                if (!in_array($statusCode, $emergencyClientStatusCodes) && !preg_match('/5[0-9][0-9]/', $statusCode)) {
54
                    $emergency = false;
55
                }
56
57
                $body = $response->getBody();
58
                try {
59
                    $sxml = new SimpleXMLElement($body);
60
61
                    foreach ($sxml->errorList as $error) {
62
                        $code = $error->error->errorCode;
63
                        $msg = $error->error->errorMessage;
64
                        $this->logger->error("Alma API error (HTTP status code: $statusCode Alma Error Code: $code): $msg");
65
                    }
66
                } catch (\Exception $e1) {
67
                    /**
68
                     *  The Alma API will return a 400 status code in the event that the API key is invalid.
69
                     *  Unfortunately, this same status code is returned under many other circumstances, for
70
                     *  example if a user provides incorrect credentials to log in.  The only way I can figure
71
                     *  out how to distinguish the two is by checking the actual text of the body, which annoyingly
72
                     *  isn't a valid XML response like all the other responses.
73
                     */
74
                    if ($body == 'Invalid API Key') {
75
                        $this->logger->emergency("@web-irt-dev Critical Error: $body :fire:");
76
                    } else {
77
                        $this->logger->error("Unable to parse response from Alma API as XML.  Status code: $statusCode  Body: $body");
78
                    }
79
                }
80
            }
81
82
            if ($emergency) {
83
                $this->logger->emergency("@web-irt-dev Critical Error: Unable to reach the Alma API! :fire:");
84
            }
85
86
            throw $e;
87
        }
88
89
        return $response;
90
    }
91
92
    /**
93
     * Get the users list of fees from Alma
94
     *
95
     * @param $userId
96
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
97
     * @throws GuzzleException
98
     */
99
    public function getUserFees($userId)
100
    {
101
        $method = 'GET';
102
        $urlPath = '/almaws/v1/users/{user_id}/fees';
103
        $templateParamNames = array('{user_id}');
104
        $templateParamValues = array(rawurlencode($userId));
105
        $query = [
106
            'user_id_type' => 'all_unique',
107
            'status' => 'ACTIVE'
108
        ];
109
        $requestParams = compact('query');
110
111
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
112
    }
113
114
    /**
115
     * Get the user from alma by the user id. Returns 400 status code if user does not exist.
116
     *
117
     * @param $userId
118
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
119
     * @throws GuzzleException
120
     */
121
    public function getUserById($userId)
122
    {
123
        $method = 'GET';
124
        $urlPath = '/almaws/v1/users/{user_id}';
125
        $templateParamNames = array('{user_id}');
126
        $templateParamValues = array(rawurlencode($userId));
127
        $query = [
128
            'user_id_type' => 'all_unique',
129
            'view' => 'full',
130
            'expand' => 'none'
131
        ];
132
        $requestParams = compact('query');
133
134
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
135
    }
136
137
    /**
138
     * @param string $userId The alphanumeric userId of the logged in user
139
     * @param string $feeId The Alma specific fee id to be updated
140
     * @param $amount
141
     * @param string $method
142
     * @param null $externalTransactionId
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $externalTransactionId is correct as it would always require null to be passed?
Loading history...
143
     * @param null $comment
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $comment is correct as it would always require null to be passed?
Loading history...
144
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
145
     * @throws GuzzleException
146
     */
147
    public function payUserFee($userId, $feeId, $amount, $method = 'ONLINE', $externalTransactionId = null, $comment = null)
148
    {
149
        $queryParams = [
150
            'op' => 'pay',
151
            'amount' => $amount,
152
            'method' => $method,
153
            'external_transaction_id' => $externalTransactionId,
154
            'comment' => $comment,
155
        ];
156
        /**
157
         * " If no callback is supplied, all entries of array equal to FALSE (see converting to boolean) will be removed."
158
         * - http://php.net/array_filter
159
         */
160
        $queryParams = array_filter($queryParams);
161
162
        return $this->updateUserFee($userId, $feeId, $queryParams);
163
    }
164
165
    /**
166
     * @param string $userId The alphanumeric userId of the logged in user
167
     * @param string $feeId The Alma specific fee id to be updated
168
     * @param array $query The parameters for the query.
169
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
170
     * @throws GuzzleException
171
     */
172
    protected function updateUserFee($userId, $feeId, $query)
173
    {
174
        $method = 'POST';
175
        $urlPath = '/almaws/v1/users/{user_id}/fees/{fee_id}';
176
        $templateParamNames = array('{user_id}', '{fee_id}');
177
        $templateParamValues = array(rawurlencode($userId), rawurlencode($feeId));
178
        $requestParams = compact('query');
179
180
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
181
    }
182
183
    /**
184
     * @param string $userId The alphanumeric userId of the logged in user
185
     * @param mixed $body A plain PHP object representing a fee.
186
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
187
     * @throws GuzzleException
188
     */
189
    public function createUserFee($userId, $body)
190
    {
191
        $method = 'POST';
192
        $urlPath = '/almaws/v1/users/{user_id}/fees';
193
        $templateParamNames = array('{user_id}');
194
        $templateParamValues = array(rawurlencode($userId));
195
196
        $headers = [
197
            'Content-Type' => 'application/json'
198
        ];
199
        $body = json_encode($body);
200
        $requestParams = compact('body', 'headers');
201
202
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
203
    }
204
205
    /**
206
     * @param string $userId The alphanumeric userId of the logged in user
207
     * @param string $userPassword The alphanumeric userPassword of the logged in user
208
     * @return mixed|null|\Psr\Http\Message\ResponseInterface
209
     * @throws GuzzleException
210
     */
211
    public function authenticateUser($userId, $userPassword)
212
    {
213
        $method = 'POST';
214
        $urlPath = '/almaws/v1/users/{user_id}';
215
        $templateParamNames = array('{user_id}');
216
        $templateParamValues = array(rawurlencode($userId));
217
        $query = [
218
            'user_id_type' => 'all_unique',
219
            'op' => 'auth'
220
        ];
221
222
        $headers = [
223
            'Exl-User-Pw' => $userPassword
224
        ];
225
        $requestParams = compact('query', 'headers');
226
227
        return $this->executeApiRequest($urlPath, $method, $requestParams, $templateParamNames, $templateParamValues);
228
    }
229
}
230