• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PiteurStudio / CourierDZ / 13103483584

02 Feb 2025 11:27PM UTC coverage: 26.042%. Remained the same
13103483584

push

github

web-flow
Merge pull request #10 from n4ss1m/refactor_rector

Refactor: Enable Rector Rules for Code Quality and Strictness

13 of 56 new or added lines in 7 files covered. (23.21%)

100 of 384 relevant lines covered (26.04%)

3.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

5.21
/src/ProviderIntegrations/ProcolisProviderIntegration.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace CourierDZ\ProviderIntegrations;
6

7
use CourierDZ\Contracts\ShippingProviderContract;
8
use CourierDZ\Exceptions\CreateOrderException;
9
use CourierDZ\Exceptions\CredentialsException;
10
use CourierDZ\Exceptions\FunctionNotSupportedException;
11
use CourierDZ\Exceptions\HttpException;
12
use CourierDZ\Exceptions\TrackingIdNotFoundException;
13
use CourierDZ\Support\ShippingProviderValidation;
14
use GuzzleHttp\Client;
15
use GuzzleHttp\Exception\GuzzleException;
16
use GuzzleHttp\Psr7\Request;
17
use http\Exception\InvalidArgumentException;
18

19
abstract class ProcolisProviderIntegration implements ShippingProviderContract
20
{
21
    use ShippingProviderValidation;
22

23
    /**
24
     * Provider credentials
25
     *
26
     * @var array<non-empty-string, non-empty-string>
27
     */
28
    private array $credentials;
29

30
    /**
31
     * Validation rules for creating an order
32
     *
33
     * @var array<non-empty-string, non-empty-string>
34
     */
35
    public array $getCreateOrderValidationRules = [
36
        'Tracking' => 'nullable|string',
37
        'TypeLivraison' => 'in:0,1', // Domicile : 0 & Stopdesk : 1
38
        'TypeColis' => 'in:0,1', // Echange : 1
39
        'Confrimee' => 'required|in:0,1', // 1 pour les colis Confirmer directement en pret a expedier ( note : if empty zr will set it to 1 because if that field is required )
40
        'Client' => 'required|string',
41
        'MobileA' => 'required|string',
42
        'MobileB' => 'nullable|string',
43
        'Adresse' => 'required|string',
44
        'IDWilaya' => 'required|numeric',
45
        'Commune' => 'required|string',
46
        'Total' => 'required|numeric',
47
        'Note' => 'nullable|string',
48
        'TProduit' => 'required|string',
49
        'id_Externe' => 'nullable|string', // Votre ID ou Tracking
50
        'Source' => 'nullable|string',
51
    ];
52

53
    /**
54
     * Create a new instance of the Procolis provider integration.
55
     *
56
     * @param  array<non-empty-string, non-empty-string>  $credentials  An array of credentials for the provider, containing the 'token' and 'key' keys
57
     *
58
     * @throws CredentialsException If the credentials do not contain the 'token' and 'key' keys
59
     */
60
    public function __construct(array $credentials)
61
    {
62
        // Check if the credentials contain the 'token' and 'key' keys
63
        if (! isset($credentials['token']) || ! isset($credentials['key'])) {
36✔
64
            throw new CredentialsException('Procolis credentials must include "token" and "key".');
12✔
65
        }
66

67
        // Store the credentials
68
        $this->credentials = $credentials;
24✔
69
    }
70

71
    // test credentials method
72

73
    /**
74
     * Tests the credentials by making a GET request to the Procolis API to retrieve
75
     * the token status. If the request is successful, the method returns true. If
76
     * the request returns a 401 status code, the method returns false. If the
77
     * request returns any other status code, the method throws an HttpException.
78
     *
79
     * @throws HttpException If the request fails
80
     */
81
    public function testCredentials(): bool
82
    {
83
        try {
84
            // Initialize Guzzle client
85
            $client = new Client;
×
86

87
            // Define the headers
88
            $headers = [
×
89
                'token' => $this->credentials['token'],
×
90
                'key' => $this->credentials['key'],
×
91
            ];
×
92

93
            // Make the GET request
94
            $response = $client->request('GET', 'https://procolis.com/api_v1/token', [
×
95
                'headers' => $headers,
×
96
            ]);
×
97

98
            // Get the response body
99
            $body = $response->getBody()->getContents();
×
100

101
            // Decode JSON response
102
            $data = json_decode($body, true);
×
103

104
            // Check the status code
105
            return match ($response->getStatusCode()) {
×
106
                // If the request is successful, return true
107
                200 => $data['Statut'] === 'Accès activé',
×
108
                // If the request returns a 401 status code, return false
109
                401 => false,
×
110
                // If the request returns any other status code, throw an HttpException
111
                default => throw new HttpException('Procolis, Unexpected error occurred.'),
×
112
            };
×
NEW
113
        } catch (GuzzleException $guzzleException) {
×
114
            // Handle exceptions
NEW
115
            throw new HttpException($guzzleException->getMessage());
×
116
        }
117

118
    }
119

120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function getRates(?int $from_wilaya_id, ?int $to_wilaya_id): array
124
    {
125
        try {
126
            // Initialize Guzzle client
127
            $client = new Client;
×
128

129
            // Define the headers
130
            $headers = [
×
131
                'token' => $this->credentials['token'],
×
132
                'key' => $this->credentials['key'],
×
133
                'Content-Type' => 'application/json',
×
134
            ];
×
135

136
            // Make the GET request
137
            $response = $client->request('POST', 'https://procolis.com/api_v1/tarification', [
×
138
                'headers' => $headers,
×
139
            ]);
×
140

141
            // Get the response body
142
            $body = $response->getBody()->getContents();
×
143

144
            $result = json_decode($body, true);
×
145

146
            // If the to_wilaya_id is specified, filter the result to only include the specified wilaya
NEW
147
            if ($to_wilaya_id !== null && $to_wilaya_id !== 0) {
×
148
                $filteredResult = [];
×
149
                foreach ($result as $wilaya) {
×
150
                    if ($wilaya['IDWilaya'] == $to_wilaya_id) {
×
151
                        $filteredResult = $wilaya;
×
152
                        break;
×
153
                    }
154
                }
155

156
                // If no matching wilaya is found, return an empty array
157
                if (empty($filteredResult)) {
×
158
                    return [];
×
159
                }
160

161
                // Return the first matching wilaya
162
                return $filteredResult;
×
163
            }
164

165
            // Decode JSON response
166
            return $result;
×
167

NEW
168
        } catch (GuzzleException $guzzleException) {
×
169
            // Handle exceptions
NEW
170
            throw new HttpException($guzzleException->getMessage());
×
171
        }
172
    }
173

174
    public function getCreateOrderValidationRules(): array
175
    {
176
        return $this->getCreateOrderValidationRules;
6✔
177
    }
178

179
    /**
180
     * {@inheritdoc}
181
     */
182
    public function createOrder(array $orderData): array
183
    {
184
        // Validate the order data
185
        $this->validateCreate($orderData);
6✔
186

187
        // Prepare the request body
188
        $data = [
×
189
            'Colis' => [
×
190
                $orderData,
×
191
            ],
×
192
        ];
×
193

194
        $requestBody = json_encode($data, JSON_UNESCAPED_UNICODE);
×
195

196
        if ($requestBody === false) {
×
197
            throw new CreateOrderException('Create Order failed ( JSON Encoding Error ) : '.json_last_error_msg());
×
198
        }
199

200
        try {
201
            // Initialize Guzzle client
202
            $client = new Client;
×
203

204
            // Define the headers
205
            $headers = [
×
206
                'token' => $this->credentials['token'],
×
207
                'key' => $this->credentials['key'],
×
208
                'Content-Type' => 'application/json',
×
209
            ];
×
210

211
            $request = new Request('POST', 'https://procolis.com/api_v1/add_colis', $headers, $requestBody);
×
212

213
            $response = $client->send($request);
×
214

215
            // Get the response body
216
            $body = $response->getBody()->getContents();
×
217

218
            $arrayResponse = json_decode($body, true);
×
219

220
            $message = $arrayResponse['Colis'][0]['MessageRetour'];
×
221

222
            // Check if the order creation was successful
223
            if ($message === 'Double Tracking') {
×
224
                throw new CreateOrderException('Create Order failed ( Duplicate `Tracking` ) : '.implode(' ', $arrayResponse['Colis'][0]));
×
225
            }
226

227
            if ($message !== 'Good') {
×
228

229
                throw new CreateOrderException('Create Order failed ( `'.$message.'` ) : '.implode(' ', $arrayResponse['Colis'][0]));
×
230
            }
231

232
            // Return the created order
233
            return $arrayResponse['Colis'][0];
×
234

NEW
235
        } catch (GuzzleException $guzzleException) {
×
236
            // Handle exceptions
NEW
237
            throw new HttpException($guzzleException->getMessage());
×
238
        }
239
    }
240

241
    /**
242
     * {@inheritdoc}
243
     */
244
    public function getOrder(string $trackingId): array
245
    {
246
        $data = [
×
247
            'Colis' => [
×
248
                ['Tracking' => $trackingId],
×
249
            ],
×
250
        ];
×
251

252
        $requestBody = json_encode($data, JSON_UNESCAPED_UNICODE);
×
253

254
        if ($requestBody === false) {
×
255
            throw new InvalidArgumentException('$trackingId must be a non-empty string');
×
256
        }
257

258
        try {
259
            // Initialize Guzzle client
260
            $client = new Client;
×
261

262
            // Define the headers
263
            $headers = [
×
264
                'token' => $this->credentials['token'],
×
265
                'key' => $this->credentials['key'],
×
266
                'Content-Type' => 'application/json',
×
267
            ];
×
268

269
            $request = new Request('POST', 'https://procolis.com/api_v1/lire', $headers, $requestBody);
×
270

271
            $response = $client->send($request);
×
272

273
            // Get the response body
274
            $body = $response->getBody()->getContents();
×
275

276
            if ($body === 'null') {
×
277
                throw new TrackingIdNotFoundException('Tracking ID not found : '.$trackingId.' , Provider : Procolis');
×
278
            }
279

280
            $arrayResponse = json_decode($body, true);
×
281

282
            // Decode JSON response
283
            return $arrayResponse['Colis'][0];
×
284

NEW
285
        } catch (GuzzleException $guzzleException) {
×
286
            // Handle exceptions
NEW
287
            throw new HttpException($guzzleException->getMessage());
×
288
        }
289
    }
290

291
    /**
292
     * @throws FunctionNotSupportedException
293
     */
294
    public function cancelOrder(string $orderId): bool
295
    {
296
        throw new FunctionNotSupportedException('Cancel order is not supported by Procolis.');
×
297
    }
298

299
    /**
300
     * @throws FunctionNotSupportedException
301
     */
302
    public function orderLabel(string $orderId): array
303
    {
304
        throw new FunctionNotSupportedException('orderLabel is not supported by Procolis.');
×
305
    }
306

307
    /**
308
     * {@inheritdoc}
309
     */
310
    abstract public static function metadata(): array;
311
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc