SMS Providers

Collapse
This is a sticky topic.
X
X
 
  • Time
  • Show
Clear All
new posts

  • robson
    replied
    SMSPlanet integration for EspoCRM (custom provider + GSM normalization)


    SMS Plante can send worldwide. I use it for Poland.

    I’ve implemented a working SMSPlanet provider for EspoCRM SMS extension and wanted to share it with the community. yuri please add to the repo if it makes sense for you

    This solution:
    • integrates with SMSPlanet API
    • supports Bearer token or key/password auth
    • forces GSM-7 encoding (removes Polish diacritics & smart characters → avoids 70-char SMS limit)
    • sets fixed sender: SSkladki.pl
    • works with Formula (ext\sms\send) and automations
    Features
    • SMSPlanet API (https://api2.smsplanet.pl/sms)
    • GSM normalization (ą→a, ę→e, etc.)
    • Handles Word/Outlook characters (quotes, dashes, etc.)
    • Multipart detection (logs segments)
    • Works with EspoCRM Sms entity
    • Production tested
    File


    Create:
    custom/Espo/Modules/SmsProviders/SmsPlanet/SmsPlanetSender.php Full code:

    <?php

    namespace Espo\Modules\SmsProviders\SmsPlanet;

    use Espo\Core\Exceptions\Error;
    use Espo\Core\Sms\Sender;
    use Espo\Core\Sms\Sms;
    use Espo\Core\Utils\Config;
    use Espo\Core\Utils\Log;
    use Espo\Core\Utils\Metadata;
    use Espo\Entities\Integration;
    use Espo\ORM\EntityManager;

    class SmsPlanetSender implements Sender
    {
    private const BASE_URL = 'https://api2.smsplanet.pl';
    private const TIMEOUT = 30;
    private const FROM_NAME = 'SSkladki.pl';
    private const FORCE_ASCII = true;

    private Config $config;
    private EntityManager $entityManager;
    private Log $log;
    private Metadata $metadata;

    public function __construct(
    Config $config,
    EntityManager $entityManager,
    Log $log,
    Metadata $metadata
    ) {
    $this->config = $config;
    $this->entityManager = $entityManager;
    $this->log = $log;
    $this->metadata = $metadata;
    }

    public function send(Sms $sms): void
    {
    foreach ($sms->getToNumberList() as $number) {
    $this->sendToNumber($sms, $number);
    }
    }

    private function sendToNumber(Sms $sms, string $toNumber): void
    {
    $integration = $this->entityManager
    ->getEntity(Integration::ENTITY_TYPE, 'SmsPlanet');

    if (!$integration || !$integration->get('enabled')) {
    throw new Error('SmsPlanet integration not enabled.');
    }

    $token = $integration->get('smsPlanetToken');

    if (!$token) {
    throw new Error('SmsPlanet: API token required.');
    }

    $body = $sms->getBody();

    if (self::FORCE_ASCII) {
    $body = self::normalizeToGsm7($body);
    }

    $to = self::formatNumber($toNumber);

    $params = http_build_query([
    'from' => self::FROM_NAME,
    'to' => $to,
    'msg' => $body,
    ]);

    $ch = curl_init(self::BASE_URL . '/sms');

    curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $params,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
    'Authorization: Bearer ' . $token,
    'Content-Type: application/x-www-form-urlencoded',
    ]
    ]);

    $response = curl_exec($ch);
    $error = curl_errno($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    curl_close($ch);

    if ($error) {
    throw new Error('SmsPlanet cURL error');
    }

    if ($status !== 200) {
    throw new Error('SmsPlanet HTTP error: ' . $status);
    }

    $decoded = json_decode($response, true);

    if (empty($decoded['messageId'])) {
    throw new Error('SmsPlanet: Invalid response');
    }
    }

    private static function formatNumber(string $number): string
    {
    $digits = preg_replace('/[^0-9]/', '', $number);

    if (strlen($digits) === 9) {
    return '+48' . $digits;
    }

    if (strlen($digits) === 11 && substr($digits, 0, 2) === '48') {
    return '+' . $digits;
    }

    return '+' . $digits;
    }

    private static function normalizeToGsm7(string $text): string
    {
    $map = [
    'ą'=>'a','ć'=>'c','ę'=>'e','ł'=>'l','ń'=>'n','ó'=> 'o','ś'=>'s','ż'=>'z','ź'=>'z',
    'Ą'=>'A','Ć'=>'C','Ę'=>'E','Ł'=>'L','Ń'=>'N','Ó'=> 'O','Ś'=>'S','Ż'=>'Z','Ź'=>'Z'
    ];

    $text = strtr($text, $map);

    $text = strtr($text, [
    '–'=>'-','—'=>'-','„'=>'"','”'=>'"',
    '’'=>"'",'…'=>'...','€'=>'EUR'
    ]);

    return preg_replace('/[^\x20-\x7E]/u', '', $text);
    }
    }

    Usage (Formula example)

    $body = 'Test SMS from EspoCRM';

    $phoneNumber = phoneNumber;

    // normalize PL numbers
    $phoneNumber = string\replace($phoneNumber, ' ', '');
    ifThen(
    string\length($phoneNumber) == 9,
    $phoneNumber = string\concatenate('+48', $phoneNumber)
    );

    $smsId = record\create(
    'Sms',
    'to', $phoneNumber,
    'body', $body
    );

    ext\sms\send($smsId);

    Notes
    • Polish characters → GSM conversion prevents SMS splitting (160 vs 70 chars)
    • Numbers without prefix are auto-converted to +48
    • Works with workflows, formulas, and automation

    Next improvements (if anyone interested)
    • SMS Templates (like Email Templates)
    • UI modal for sending SMS from Lead/Contact
    • Delivery status (DLR webhook)
    Attached Files

    Leave a comment:


  • axyl
    replied
    I created an extension, which uses the SMS Providers Extension to let users send SMS from Contacts, etc.

    Forum post is here.
    Hey Everyone, I needed a way to let staff send ad-hoc SMS's when looking at contacts and some custom Entities. I've created that as an extension and put it on Github if anyone else wants to use it or use it as a base for their own tweaks. We use this with branded SMS's, so I didn't need to handle replies. Code is here -

    Leave a comment:


  • Dozent
    replied
    Hi. You can do provider integration RocketSMS. He has an API

    Leave a comment:


  • Kritika
    replied
    Hello. can you add a provider?
    SMS Центр – сервис для отправки и приема SMS-сообщений, EMS и бинарные SMS, E-mail2sms, HLR, MMS, Voice, E-mail рассылки и другое. Гарантированная доставка сообщений по всему миру, удобные тарифы и API-интеграция.

    Leave a comment:


  • mkas
    replied
    Originally posted by Kyle
    2FA can send SMS
    Formula
    or write some code

    There is no user ability to send an SMS
    Awesome, thanks.

    Leave a comment:


  • Kyle
    replied
    2FA can send SMS
    Formula
    or write some code

    There is no user ability to send an SMS

    Leave a comment:


  • mkas
    replied
    I have installed this and added my Twilio credentials.
    How do you actually use it to send SMS?

    Leave a comment:


  • rabii
    commented on 's reply
    Thanks for pointing me into how to do it, i thought it might need other configuration but it straight config. works like a charm

  • alexisc
    replied
    can you add a local provider?

    Leave a comment:


  • yuri
    replied
    Hi,

    You need to create a pull request so that your commits could be merged into the original repository.

    Leave a comment:


  • item
    replied
    Hello Yuri,
    i just begin github.. i have make one new smsProvider from belgium..
    i have clone.. and make a push.. don't kill me if i am bad
    i am beginner.. i don't know if you see.. but..

    Best Regards

    Attached Files

    Leave a comment:


  • item
    commented on 's reply
    Hi,
    Remove last , in the files
    No time now.. tommorow

  • sapyantuk
    replied
    Hello, item Thank you so much for Helping . I just tried to install the extension. After installing extension i got one error


    Error 500: JSON syntax error in 'custom/Espo/Modules/SmsProvidersNepal/Resources/i18n/en_US/Integration.json'

    I can provide you Details for Testing

    i have send you Private message for token and other details needed for integration

    Thanks in Advance

    Leave a comment:


  • item
    replied
    Hi you can try...
    i can't test but if bug, certainly easily working state
    Attached Files

    Leave a comment:


  • yuri
    commented on 's reply
    Sorry, I have other things to do.
Working...