Skip to content

Commit ffc04a3

Browse files
committed
Refactor composer.json for broader PHP and Laravel support, remove deprecated files, and enhance README with new features and webhook integration details.
1 parent 0c7f60f commit ffc04a3

File tree

9 files changed

+365
-201
lines changed

9 files changed

+365
-201
lines changed

README.md

Lines changed: 258 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,23 @@ A Laravel package for seamless integration with the OTPIQ SMS service API. Send
1313
## ✨ Features
1414

1515
- **Multi-Channel Messaging**: Send messages via SMS, WhatsApp, or Telegram.
16-
- **Verification Codes**: Easily send OTPs and verification codes.
16+
- **Verification Codes**: Send OTP verification codes easily.
1717
- **Custom Messages**: Send personalized messages with approved sender IDs.
18-
- **Delivery Tracking**: Track the status of sent messages in real-time.
18+
- **Delivery Tracking**: Track the status of sent messages with detailed channel flow.
1919
- **Credit Management**: Monitor your remaining credits and usage.
2020
- **Sender ID Management**: Retrieve and manage your approved sender IDs.
21-
- **Laravel 10+ Support**: Fully compatible with Laravel 10 and above.
22-
- **PHP 8.1+ Support**: Built for modern PHP applications.
21+
- **Webhooks Support**: Real-time notifications for message status updates.
22+
- **Error Handling**: Comprehensive exception handling.
23+
- **Laravel 10-12 Support**: Fully compatible with Laravel 10, 11, and 12.
24+
- **PHP 8.1-8.4 Support**: Built for modern PHP applications.
2325

2426
---
2527

2628
## 🛠️ Requirements
2729

28-
- PHP 8.1 or higher
29-
- Laravel 10 or higher
30+
- PHP 8.1, 8.2, 8.3, or 8.4
31+
- Laravel 10, 11, or 12
32+
- Guzzle HTTP 7.0+
3033

3134
---
3235

@@ -72,32 +75,35 @@ return [
7275
use Rstacode\Otpiq\Facades\Otpiq;
7376

7477
$response = Otpiq::sendSms([
75-
'phoneNumber' => '9647501234567',
78+
'phoneNumber' => '964750123456',
7679
'smsType' => 'verification',
7780
'verificationCode' => '123456',
78-
'provider' => 'auto' // Optional (default: auto)
81+
'provider' => 'whatsapp-telegram-sms' // Optional (recommended)
7982
]);
8083

8184
// Response:
8285
// [
8386
// 'message' => 'SMS task created successfully',
84-
// 'smsId' => 'sms-1234567890',
85-
// 'remainingCredit' => 920,
86-
// 'provider' => 'telegram',
87-
// 'status' => 'pending'
87+
// 'smsId' => 'sms-1234567890abcdef123456',
88+
// 'remainingCredit' => 14800,
89+
// 'cost' => 200,
90+
// 'canCover' => true,
91+
// 'paymentType' => 'prepaid'
8892
// ]
8993
```
9094

9195
### Send Custom Message
9296

9397
```php
9498
$response = Otpiq::sendSms([
95-
'phoneNumber' => '9647501234567',
99+
'phoneNumber' => '964750123456',
96100
'smsType' => 'custom',
97101
'customMessage' => 'Special offer! 20% discount today!',
98-
'senderId' => 'MyStore',
102+
'senderId' => 'OTPIQ',
99103
'provider' => 'sms' // Required for custom messages
100104
]);
105+
106+
// Response: Same as verification code response above
101107
```
102108

103109
### Track SMS Status
@@ -107,10 +113,23 @@ $status = Otpiq::trackSms('sms-1234567890');
107113

108114
// Response:
109115
// [
110-
// 'status' => 'delivered',
111-
// 'phoneNumber' => '9647501234567',
112-
// 'smsId' => 'sms-1234567890',
113-
// 'cost' => 80
116+
// 'smsId' => 'sms-1234567890abcdef123456',
117+
// 'phoneNumber' => '964750123456',
118+
// 'status' => 'sent',
119+
// 'cost' => 200,
120+
// 'isFinalStatus' => false,
121+
// 'lastChannel' => 'whatsapp',
122+
// 'channelFlow' => [
123+
// [
124+
// 'channel' => 'whatsapp',
125+
// 'tried' => true,
126+
// 'success' => true
127+
// ],
128+
// [
129+
// 'channel' => 'sms',
130+
// 'tried' => false
131+
// ]
132+
// ]
114133
// ]
115134
```
116135

@@ -119,9 +138,15 @@ $status = Otpiq::trackSms('sms-1234567890');
119138
```php
120139
$projectInfo = Otpiq::getProjectInfo();
121140

141+
// Response:
142+
// [
143+
// 'projectName' => 'My SMS Project',
144+
// 'credit' => 15000
145+
// ]
146+
122147
// Access project info:
123-
echo $projectInfo['projectName']; // "My Project"
124-
echo $projectInfo['credit']; // 1000
148+
echo $projectInfo['projectName']; // "My SMS Project"
149+
echo $projectInfo['credit']; // 15000
125150
```
126151

127152
### Get Sender IDs
@@ -131,12 +156,18 @@ $senderIds = Otpiq::getSenderIds();
131156

132157
// Response:
133158
// [
134-
// 'senderIds' => [
159+
// 'success' => true,
160+
// 'data' => [
135161
// [
136-
// 'id' => 'sender-123',
137-
// 'senderId' => 'MyBrand',
162+
// '_id' => '507f1f77bcf86cd799439011',
163+
// 'senderId' => 'OTPIQ',
138164
// 'status' => 'accepted',
139-
// 'createdAt' => '2024-01-01T00:00:00.000Z'
165+
// 'pricePerSms' => [
166+
// 'korekTelecom' => 80,
167+
// 'asiaCell' => 80,
168+
// 'zainIraq' => 80,
169+
// 'others' => 100
170+
// ]
140171
// ]
141172
// ]
142173
// ]
@@ -173,40 +204,226 @@ try {
173204

174205
## 🔌 Available Providers
175206

176-
When sending messages, you can specify the provider:
207+
OTPIQ offers 6 provider options including smart fallback routes:
177208

178-
- `auto` (recommended): System automatically chooses the best available provider.
179-
- `sms`: Send via SMS.
180-
- `whatsapp`: Send via WhatsApp.
181-
- `telegram`: Send via Telegram.
209+
- `whatsapp-telegram-sms` (recommended): Try WhatsApp → Telegram → SMS (maximum delivery success)
210+
- `whatsapp-sms`: Try WhatsApp first, fallback to SMS
211+
- `telegram-sms`: Try Telegram first, fallback to SMS
212+
- `sms`: SMS only
213+
- `whatsapp`: WhatsApp only
214+
- `telegram`: Telegram only
182215

183-
**Note**: When `smsType` is `custom`, the provider is automatically set to `sms`.
216+
**Note**: For custom messages, the provider is typically set to `sms` since sender IDs are mainly supported via SMS.
184217

185218
---
186219

187-
## 🧪 Testing
220+
## 🔗 Webhooks
221+
222+
OTPIQ provides real-time delivery status notifications via webhooks. When you configure webhooks, you'll receive instant updates about message delivery status directly to your server.
223+
224+
### How to Configure Webhooks
225+
226+
Include a `deliveryReport` object in your SMS request:
227+
228+
```php
229+
$response = Otpiq::sendSms([
230+
'phoneNumber' => '964750123456',
231+
'smsType' => 'verification',
232+
'verificationCode' => '123456',
233+
'deliveryReport' => [
234+
'webhookUrl' => 'https://your-app.com/webhooks/sms-status',
235+
'deliveryReportType' => 'all', // 'all' or 'final'
236+
'webhookSecret' => 'your_secret_123' // Optional
237+
]
238+
]);
239+
```
240+
241+
### Webhook Configuration Fields
242+
243+
| Field | Type | Required | Description |
244+
| -------------------- | ------ | -------- | -------------------------------------------------------- |
245+
| `webhookUrl` | string | Yes | HTTPS URL where status updates are sent |
246+
| `deliveryReportType` | string | No | `"all"` for all updates, `"final"` for final status only |
247+
| `webhookSecret` | string | No | Secret key for webhook authentication |
248+
249+
### Webhook Payload Structure
250+
251+
Each webhook request contains a JSON payload with these fields:
252+
253+
**Required Fields:**
254+
255+
- `smsId`: Unique message identifier
256+
- `deliveryReportType`: Your configured report type
257+
- `isFinal`: Whether this is the final status
258+
- `channel`: Messaging channel (sms, whatsapp, telegram)
259+
- `status`: Delivery status (sent, delivered, failed)
260+
261+
**Optional Fields:**
262+
263+
- `reason`: Failure reason (only when status is 'failed')
264+
- `senderId`: Sender ID used (only for SMS with custom sender IDs)
265+
266+
### Delivery Status Flow
267+
268+
**SMS Messages:**
269+
270+
- `sent` → Message accepted by carrier
271+
- `delivered` → Message confirmed delivered to recipient
272+
- `failed` → Message could not be delivered
273+
274+
**WhatsApp Messages:**
275+
276+
- `sent` → Message sent to WhatsApp servers
277+
- `delivered` → Message delivered to recipient's device
278+
- `failed` → Message could not be sent or delivered
279+
280+
**Telegram Messages:**
281+
282+
- `sent` → Message sent to Telegram servers
283+
- `delivered` → Message delivered to recipient
284+
- `failed` → Message could not be sent
285+
286+
### Webhook Examples
287+
288+
#### Example 1: SMS with Custom Sender ID
188289

189-
Run the test suite:
290+
**Request:**
190291

191-
```bash
192-
composer test
292+
```php
293+
$response = Otpiq::sendSms([
294+
'phoneNumber' => '964750123456',
295+
'smsType' => 'custom',
296+
'customMessage' => 'Your order has been confirmed!',
297+
'senderId' => 'OTPIQ',
298+
'deliveryReport' => [
299+
'webhookUrl' => 'https://your-app.com/webhooks/sms-status',
300+
'deliveryReportType' => 'all',
301+
'webhookSecret' => 'your_secret_123'
302+
]
303+
]);
304+
```
305+
306+
**Webhook Payloads Received:**
307+
308+
Sent Status:
309+
310+
```json
311+
{
312+
"smsId": "sms_1234567890abcdef",
313+
"deliveryReportType": "all",
314+
"isFinal": false,
315+
"channel": "sms",
316+
"status": "sent",
317+
"senderId": "OTPIQ"
318+
}
319+
```
320+
321+
Delivered Status:
322+
323+
```json
324+
{
325+
"smsId": "sms_1234567890abcdef",
326+
"deliveryReportType": "all",
327+
"isFinal": true,
328+
"channel": "sms",
329+
"status": "delivered",
330+
"senderId": "OTPIQ"
331+
}
332+
```
333+
334+
#### Example 2: WhatsApp with Final-Only Reports
335+
336+
**Request:**
337+
338+
```php
339+
$response = Otpiq::sendSms([
340+
'phoneNumber' => '964750123456',
341+
'smsType' => 'verification',
342+
'verificationCode' => '123456',
343+
'provider' => 'whatsapp',
344+
'deliveryReport' => [
345+
'webhookUrl' => 'https://your-app.com/webhooks/whatsapp-status',
346+
'deliveryReportType' => 'final'
347+
]
348+
]);
193349
```
194350

195-
Run specific tests:
351+
**Webhook Payload (Final Status Only):**
196352

197-
```bash
198-
./vendor/bin/phpunit tests/Unit/OtpiqServiceTest.php
353+
```json
354+
{
355+
"smsId": "sms_1234567890abcdef",
356+
"deliveryReportType": "final",
357+
"isFinal": true,
358+
"channel": "whatsapp",
359+
"status": "delivered"
360+
}
199361
```
200362

201-
Mock API responses in tests:
363+
#### Example 3: Failed Message
364+
365+
**Request:**
202366

203367
```php
204-
Otpiq::fake([
205-
'info' => ['projectName' => 'Test Project', 'credit' => 5000],
206-
'sms' => ['smsId' => 'test-123', 'status' => 'queued']
368+
$response = Otpiq::sendSms([
369+
'phoneNumber' => '964750123456',
370+
'smsType' => 'custom',
371+
'customMessage' => 'Your order has been confirmed!',
372+
'senderId' => 'OTPIQ',
373+
'deliveryReport' => [
374+
'webhookUrl' => 'https://your-app.com/webhooks/sms-status',
375+
'deliveryReportType' => 'final'
376+
]
207377
]);
208378
```
209379

380+
**Webhook Payload (Failure):**
381+
382+
```json
383+
{
384+
"smsId": "sms_abcdef1234567890",
385+
"deliveryReportType": "final",
386+
"isFinal": true,
387+
"channel": "sms",
388+
"status": "failed",
389+
"reason": "Carrier rejected the message",
390+
"senderId": "OTPIQ"
391+
}
392+
```
393+
394+
### Laravel Event Integration
395+
396+
For handling webhook events in Laravel:
397+
398+
```php
399+
// In routes/web.php
400+
Route::post('/webhooks/sms-status', function (Request $request) {
401+
$payload = $request->all();
402+
403+
// Verify webhook signature (for security)
404+
// $signature = $request->header('X-OTPIQ-Signature');
405+
406+
switch ($payload['status']) {
407+
case 'delivered':
408+
// Handle delivered event
409+
Log::info("SMS {$payload['smsId']} delivered via {$payload['channel']}");
410+
break;
411+
412+
case 'failed':
413+
// Handle failed event
414+
Log::error("SMS {$payload['smsId']} failed: {$payload['reason']}");
415+
break;
416+
417+
case 'sent':
418+
// Handle sent event
419+
Log::info("SMS {$payload['smsId']} sent via {$payload['channel']}");
420+
break;
421+
}
422+
423+
return response()->json(['status' => 'ok']);
424+
});
425+
```
426+
210427
---
211428

212429
## 📜 License

0 commit comments

Comments
 (0)