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

PiteurStudio / CourierDZ / 13101535973

02 Feb 2025 06:48PM UTC coverage: 26.042%. First build
13101535973

Pull #9

github

web-flow
Merge a8aadf6dd into 4fe37b9d1
Pull Request #9: improve composer test scripts

1 of 23 new or added lines in 5 files covered. (4.35%)

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

0.0
/src/ProviderIntegrations/YalidineProviderIntegration.php
1
<?php
2

3
namespace CourierDZ\ProviderIntegrations;
4

5
use CourierDZ\Contracts\ShippingProviderContract;
6
use CourierDZ\Exceptions\CreateOrderException;
7
use CourierDZ\Exceptions\CredentialsException;
8
use CourierDZ\Exceptions\HttpException;
9
use CourierDZ\Exceptions\TrackingIdNotFoundException;
10
use CourierDZ\Support\ShippingProviderValidation;
11
use GuzzleHttp\Client;
12
use GuzzleHttp\Exception\GuzzleException;
13
use GuzzleHttp\Psr7\Request;
14

15
abstract class YalidineProviderIntegration implements ShippingProviderContract
16
{
17
    use ShippingProviderValidation;
18

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

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

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

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

72
        // Set the credentials
73
        $this->credentials = $credentials;
×
74
    }
75

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

203
            $message = $arrayResponse[$orderData['id']]['message'];
×
204

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

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

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

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

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

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

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

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

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

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

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

265
        } catch (GuzzleException $e) {
×
266
            // Handle exceptions
267
            throw new HttpException($e->getMessage());
×
268
        }
269
    }
270
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc