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

PiteurStudio / CourierDZ / 17917521991

22 Sep 2025 01:51PM UTC coverage: 44.248%. Remained the same
17917521991

Pull #19

github

web-flow
Merge 2169dfe40 into 6b1b06c7f
Pull Request #19: yalidine updates

0 of 3 new or added lines in 1 file covered. (0.0%)

300 of 678 relevant lines covered (44.25%)

5.48 hits per line

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

0.0
/src/ProviderIntegrations/YalidineProviderIntegration.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\HttpException;
11
use CourierDZ\Exceptions\TrackingIdNotFoundException;
12
use CourierDZ\Support\ShippingProviderValidation;
13
use GuzzleHttp\Client;
14
use GuzzleHttp\Exception\GuzzleException;
15
use GuzzleHttp\Psr7\Request;
16

17
abstract class YalidineProviderIntegration implements ShippingProviderContract
18
{
19
    use ShippingProviderValidation;
20

21
    /**
22
     * Provider credentials
23
     *
24
     * @var array<non-empty-string, non-empty-string>
25
     */
26
    protected array $credentials;
27

28
    /**
29
     * Validation rules for creating an order
30
     *
31
     * @var array<non-empty-string, non-empty-string>
32
     */
33
    public array $getCreateOrderValidationRules = [
34
        'order_id' => 'required|string',
35
        'from_wilaya_name' => 'required|string',
36
        'firstname' => 'required|string',
37
        'familyname' => 'required|string',
38
        'contact_phone' => 'required|string',
39
        'address' => 'required|string',
40
        'to_commune_name' => 'required|string',
41
        'to_wilaya_name' => 'required|string',
42
        'product_list' => 'required|string',
43
        'price' => 'required|numeric|min:0|max:150000',
44
        'do_insurance' => 'required|boolean',
45
        'declared_value' => 'required|numeric|min:0|max:150000',
46
        'length' => 'required|numeric|min:0',
47
        'width' => 'required|numeric|min:0',
48
        'height' => 'required|numeric|min:0',
49
        'weight' => 'required|numeric|min:0',
50
        'freeshipping' => 'required|boolean',
51
        'is_stopdesk' => 'required|boolean',
52
        'stopdesk_id' => 'required_if:is_stopdesk,true|string',
53
        'has_exchange' => 'required|boolean',
54
        'product_to_collect' => 'sometimes|nullable',
55
    ];
56

57
    /**
58
     * Constructor
59
     *
60
     * @param  array<non-empty-string, non-empty-string>  $credentials  The provider credentials
61
     *
62
     * @throws CredentialsException
63
     */
64
    public function __construct(array $credentials)
65
    {
66
        // Get the provider name from the metadata
67
        $provider_name = static::metadata()['name'];
×
68

69
        // Check if the credentials are valid
70
        if (! isset($credentials['id']) || ! isset($credentials['token'])) {
×
71
            throw new CredentialsException($provider_name.' credentials must include "id" and "token".');
×
72
        }
73

74
        // Set the credentials
75
        $this->credentials = $credentials;
×
76
    }
77

78
    /**
79
     * Get provider metadata
80
     */
81
    abstract public static function metadata(): array;
82

83
    /**
84
     * Get the API domain
85
     */
86
    abstract public static function apiDomain(): string;
87

88
    /**
89
     * Test credentials
90
     *
91
     * Makes a GET request to the /wilayas endpoint to check if the credentials are valid.
92
     * If the request is successful (200 status code), the credentials are valid.
93
     * If the request returns a 401 or 500 status code, the credentials are invalid.
94
     * Any other status code is considered an unexpected error.
95
     *
96
     * @throws HttpException
97
     */
98
    public function testCredentials(): bool
99
    {
100
        try {
101
            // Initialize Guzzle client
102
            $client = new Client(['http_errors' => false]);
×
103

104
            // Define the headers
105
            $headers = [
×
106
                'X-API-ID' => $this->credentials['id'],
×
107
                'X-API-TOKEN' => $this->credentials['token'],
×
108
            ];
×
109

110
            // Make the GET request
111
            $response = $client->request('GET', static::apiDomain().'/v1/wilayas/', [
×
112
                'headers' => $headers,
×
113
            ]);
×
114

115
            // If the request is successful, the credentials are valid
116
            if ($response->getStatusCode() === 200) {
×
117
                return true;
×
118
            }
119

120
            // If the request returns a 401 or 500 status code, the credentials are invalid
121
            if (in_array($response->getStatusCode(), [401, 500])) {
×
122
                return false;
×
123
            }
124

125
            // Any other status code is considered an unexpected error
126
            throw new HttpException('Yalidine, Unexpected error occurred.');
×
127
        } catch (GuzzleException $guzzleException) {
×
128
            // Handle exceptions
129
            throw new HttpException($guzzleException->getMessage());
×
130
        }
131
    }
132

133
    /**
134
     * Get rates
135
     *
136
     * @throws HttpException
137
     */
138
    public function getRates(?int $from_wilaya_id = null, ?int $to_wilaya_id = null): array
139
    {
140
        try {
141
            // Initialize Guzzle client
142
            $client = new Client(['http_errors' => false]);
×
143

144
            // Define the headers
145
            $headers = [
×
146
                'X-API-ID' => $this->credentials['id'],
×
147
                'X-API-TOKEN' => $this->credentials['token'],
×
148
            ];
×
149

150
            // Make the GET request
151
            $response = $client->request('GET', static::apiDomain().'/v1/fees/?from_wilaya_id='.$from_wilaya_id.'&to_wilaya_id='.$to_wilaya_id, [
×
152
                'headers' => $headers,
×
153
            ]);
×
154

155
            // Return the response body as an array
156
            return json_decode($response->getBody()->getContents(), true);
×
157

158
        } catch (GuzzleException $guzzleException) {
×
159
            // Handle exceptions
160
            throw new HttpException($guzzleException->getMessage());
×
161
        }
162
    }
163

164
    public function getCreateOrderValidationRules(): array
165
    {
166
        return $this->getCreateOrderValidationRules;
×
167
    }
168

169
    /**
170
     * {@inheritdoc}
171
     */
172
    public function createOrder(array $orderData): array
173
    {
174
        $this->validateCreate($orderData);
×
175

176
        try {
177
            // Initialize Guzzle client
178
            $client = new Client;
×
179

180
            // Define the headers
181
            $headers = [
×
182
                'X-API-ID' => $this->credentials['id'],
×
183
                'X-API-TOKEN' => $this->credentials['token'],
×
184
                'Content-Type' => 'application/json',
×
185
            ];
×
186

187
            $requestBody = json_encode([$orderData], JSON_UNESCAPED_UNICODE);
×
188

189
            if ($requestBody === false) {
×
190
                throw new CreateOrderException('Create Order failed : JSON encoding error');
×
191
            }
192

193
            $request = new Request('POST', static::apiDomain().'/v1/parcels/', $headers, $requestBody);
×
194

195
            $response = $client->send($request);
×
196

197
            // Get the response body
198
            $body = $response->getBody()->getContents();
×
199

200
            $arrayResponse = json_decode($body, true);
×
201

NEW
202
            $message = $arrayResponse[$orderData['order_id']]['message'];
×
203

204
            // Check if the order creation was successful
NEW
205
            if ($arrayResponse[$orderData['order_id']]['success'] != 'true') {
×
NEW
206
                throw new CreateOrderException('Create Order failed ( `'.$message.'` ) : '.implode(' ', $arrayResponse[$orderData['order_id']]));
×
207
            }
208

209
            // Return the created order
210
            return $arrayResponse[$orderData['id']];
×
211

212
        } catch (GuzzleException $guzzleException) {
×
213
            // Handle exceptions
214
            throw new HttpException($guzzleException->getMessage());
×
215
        }
216
    }
217

218
    /**
219
     * {@inheritdoc}
220
     */
221
    public function orderLabel(string $orderId): array
222
    {
223
        // Get order details
224
        $order = $this->getOrder($orderId);
×
225

226
        // Return the label URL as an associative array
227
        return [
×
228
            'type' => 'url',
×
229
            'data' => $order['label'],
×
230
        ];
×
231
    }
232

233
    /**
234
     * Read order details
235
     *
236
     * @throws HttpException
237
     * @throws TrackingIdNotFoundException
238
     */
239
    public function getOrder(string $trackingId): array
240
    {
241
        try {
242
            // Initialize Guzzle client
243
            $client = new Client(['http_errors' => false]);
×
244

245
            // Define the headers
246
            $headers = [
×
247
                'X-API-ID' => $this->credentials['id'],
×
248
                'X-API-TOKEN' => $this->credentials['token'],
×
249
            ];
×
250

251
            // Make the GET request
252
            $response = $client->request('GET', 'https://api.yalidine.app/v1/parcels/'.$trackingId, [
×
253
                'headers' => $headers,
×
254
            ]);
×
255

256
            $data = json_decode($response->getBody()->getContents(), true);
×
257

258
            if ($data['total_data'] == 0) {
×
259
                throw new TrackingIdNotFoundException('Tracking ID not found : '.$trackingId.' , Provider : Yalidine');
×
260
            }
261

262
            return $data['data'][0];
×
263

264
        } catch (GuzzleException $guzzleException) {
×
265
            // Handle exceptions
266
            throw new HttpException($guzzleException->getMessage());
×
267
        }
268
    }
269
}
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