Skip to content

Commit

Permalink
Merge pull request #16 from byawitz/feat-adding-sms-adapters
Browse files Browse the repository at this point in the history
Feat adding sms adapters
  • Loading branch information
abnegate authored Sep 14, 2023
2 parents a14b8ac + 0aef44f commit 2d0f474
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 5 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ $messaging->send($message);
- [x] [TextMagic](https://www.textmagic.com/)
- [x] [Msg91](https://msg91.com/)
- [x] [Vonage](https://www.vonage.com/)
- [ ] [Plivo](https://www.plivo.com/)
- [ ] [Infobip](https://www.infobip.com/)
- [ ] [Clickatell](https://www.clickatell.com/)
- [x] [Plivo](https://www.plivo.com/)
- [x] [Infobip](https://www.infobip.com/)
- [x] [Clickatell](https://www.clickatell.com/)
- [ ] [AfricasTalking](https://africastalking.com/)
- [ ] [Sinch](https://www.sinch.com/)
- [ ] [Sms77](https://www.sms77.io/)
- [x] [Sinch](https://www.sinch.com/)
- [x] [Seven](https://www.seven.io/)
- [ ] [SmsGlobal](https://www.smsglobal.com/)

### Push
Expand Down
64 changes: 64 additions & 0 deletions docs/sms-pricing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# SMS Provider pricing

### In case you wonder which provider will suite you with best price

- _The list includes only implemented providers_
- _The list is sorted by unit price low -> high_

## SMS Target

_You can add your country with a full pricing table._

- [United States](#united-states)
- [India](#india)
- [Israel](#israel)

## United States

_In most providers when you're sending SMS to US numbers you must own a US phone number to provide it in the `from` field. Other might add random phone number they have_

| Provider | Unit Price | 10K |
|------------|------------|-------|
| Plivo | 0.0050 | 50 $ |
| Telesign | 0.0062 | 62 $ |
| Msg91 | 0.0067 | 67 $ |
| Vonage | 0.0067 | 67 $ |
| Infobip | 0.0070 | 70 $ |
| Clickatell | 0.0075 | 75 $ |
| Twilio | 0.0079 | 79 $ |
| Sinch | 0.0120 | 120 $ |
| TextMagic | 0.0400 | 400 $ |
| Telnyx | 0.0440 | 440 $ |
| Seven | 0.0810 | 810 $ |

## India

| Provider | Unit Price | 10K |
|------------|------------|-------|
| Msg91 | 0.0030 | 30 $ |
| Clickatell | 0.0426 | 426 $ |
| Vonage | 0.0449 | 449 $ |
| Telesign | 0.0485 | 485 $ |
| Telnyx | 0.0490 | 490 $ |
| Twilio | 0.0490 | 490 $ |
| Plivo | 0.0560 | 560 $ |
| Seven | 0.0810 | 810 $ |
| Infobip | n/a | |
| Sinch | n/a | |
| TextMagic | n/a | |

## Israel

| Provider | Unit Price | 10K |
|------------|------------|----------|
| Telesign | 0.0768 | 768 $ |
| Seven | 0.0810 | 810 $ |
| Msg91 | 0.0845 | 845 $ |
| Plivo | 0.101 | 1010 $ |
| Vonage | 0.1019 | 1019 $ |
| Infobip | 0.106 | 1060 $ |
| Telnyx | 0.1100 | 1100 $ |
| Twilio | 0.112 | 1120 $ |
| Clickatell | 0.13144 | 1314.4 $ |
| Sinch | n/a | |
| TextMagic | n/a | |
51 changes: 51 additions & 0 deletions src/Utopia/Messaging/Adapters/SMS/Clickatell.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Utopia\Messaging\Adapters\SMS;

use Utopia\Messaging\Adapters\SMS as SMSAdapter;
use Utopia\Messaging\Messages\SMS;

// Reference Material
// https://docs.clickatell.com/channels/sms-channels/sms-api-reference/#tag/SMS-API/operation/sendMessageREST_1
class Clickatell extends SMSAdapter
{
/**
* @param string $apiKey Clickatell API Key
*/
public function __construct(
private string $apiKey,
) {
}

public function getName(): string
{
return 'Clickatell';
}

public function getMaxMessagesPerRequest(): int
{
return 500;
}

/**
* {@inheritdoc}
*
* @throws \Exception
*/
protected function process(SMS $message): string
{
return $this->request(
method: 'POST',
url: 'https://platform.clickatell.com/messages',
headers: [
'content-type: application/json',
'Authorization: '.$this->apiKey,
],
body: \json_encode([
'content' => $message->getContent(),
'from' => $message->getFrom(),
'to' => $message->getTo(),
]),
);
}
}
57 changes: 57 additions & 0 deletions src/Utopia/Messaging/Adapters/SMS/Infobip.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Utopia\Messaging\Adapters\SMS;

use Utopia\Messaging\Adapters\SMS as SMSAdapter;
use Utopia\Messaging\Messages\SMS;

// Reference Material
// https://www.infobip.com/docs/api/channels/sms/sms-messaging/outbound-sms/send-sms-message
class Infobip extends SMSAdapter
{
/**
* @param string $apiBaseUrl Infobip API Base Url
* @param string $apiKey Infobip API Key
*/
public function __construct(
private string $apiBaseUrl,
private string $apiKey
) {
}

public function getName(): string
{
return 'Infobip';
}

public function getMaxMessagesPerRequest(): int
{
return 1000;
}

/**
* {@inheritdoc}
*
* @throws \Exception
*/
protected function process(SMS $message): string
{
$to = \array_map(fn ($number) => ['to' => \ltrim($number, '+')], $message->getTo());

return $this->request(
method: 'POST',
url: "https://{$this->apiBaseUrl}/sms/2/text/advanced",
headers: [
'Authorization: App '.$this->apiKey,
'content-type: application/json',
],
body: \json_encode([
'messages' => [
'text' => $message->getContent(),
'from' => $message->getFrom(),
'destinations' => $to,
],
]),
);
}
}
52 changes: 52 additions & 0 deletions src/Utopia/Messaging/Adapters/SMS/Plivo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Utopia\Messaging\Adapters\SMS;

use Utopia\Messaging\Adapters\SMS as SMSAdapter;
use Utopia\Messaging\Messages\SMS;

// Reference Material
// https://www.plivo.com/docs/sms/api/message#send-a-message
class Plivo extends SMSAdapter
{
/**
* @param string $authId Plivo Auth ID
* @param string $authToken Plivo Auth Token
*/
public function __construct(
private string $authId,
private string $authToken
) {
}

public function getName(): string
{
return 'Plivo';
}

public function getMaxMessagesPerRequest(): int
{
return 1000;
}

/**
* {@inheritdoc}
*
* @throws \Exception
*/
protected function process(SMS $message): string
{
return $this->request(
method: 'POST',
url: "https://api.plivo.com/v1/Account/{$this->authId}/Message/",
headers: [
'Authorization: Basic '.base64_encode("{$this->authId}:{$this->authToken}"),
],
body: \http_build_query([
'text' => $message->getContent(),
'src' => $message->getFrom() ?? 'Plivo',
'dst' => \implode('<', $message->getTo()),
]),
);
}
}
51 changes: 51 additions & 0 deletions src/Utopia/Messaging/Adapters/SMS/Seven.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Utopia\Messaging\Adapters\SMS;

use Utopia\Messaging\Adapters\SMS as SMSAdapter;
use Utopia\Messaging\Messages\SMS;

// Reference Material
// https://www.seven.io/en/docs/gateway/http-api/sms-dispatch/
class Seven extends SMSAdapter
{
/**
* @param string $apiKey Seven API token
*/
public function __construct(
private string $apiKey
) {
}

public function getName(): string
{
return 'Seven';
}

public function getMaxMessagesPerRequest(): int
{
return 1000;
}

/**
* {@inheritdoc}
*
* @throws \Exception
*/
protected function process(SMS $message): string
{
return $this->request(
method: 'POST',
url: 'https://gateway.sms77.io/api/sms',
headers: [
'Authorization: Basic '.$this->apiKey,
'content-type: application/json',
],
body: \json_encode([
'from' => $message->getFrom(),
'to' => \implode(',', $message->getTo()),
'text' => $message->getContent(),
]),
);
}
}
55 changes: 55 additions & 0 deletions src/Utopia/Messaging/Adapters/SMS/Sinch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Utopia\Messaging\Adapters\SMS;

use Utopia\Messaging\Adapters\SMS as SMSAdapter;
use Utopia\Messaging\Messages\SMS;

// Reference Material
// https://developers.sinch.com/docs/sms/api-reference/
class Sinch extends SMSAdapter
{
/**
* @param string $servicePlanId Sinch Service plan ID
* @param string $apiToken Sinch API token
*/
public function __construct(
private string $servicePlanId,
private string $apiToken
) {
}

public function getName(): string
{
return 'Sinch';
}

public function getMaxMessagesPerRequest(): int
{
return 1000;
}

/**
* {@inheritdoc}
*
* @throws \Exception
*/
protected function process(SMS $message): string
{
$to = \array_map(fn ($number) => \ltrim($number, '+'), $message->getTo());

return $this->request(
method: 'POST',
url: "https://sms.api.sinch.com/xms/v1/{$this->servicePlanId}/batches",
headers: [
'Authorization: Bearer '.$this->apiToken,
'content-type: application/json',
],
body: \json_encode([
'from' => $message->getFrom(),
'to' => $to,
'body' => $message->getContent(),
]),
);
}
}

0 comments on commit 2d0f474

Please sign in to comment.