From 23e90e0736d18407e77d4fd3f4423411b70ac0a7 Mon Sep 17 00:00:00 2001 From: Yousra Ashraf Date: Tue, 1 Sep 2026 09:36:00 +0300 Subject: [PATCH] feat: add Community Ads SMS provider --- README.md | 17 +++- config/resala.php | 10 +++ .../PublishProviderEnvVariablesCommand.php | 4 + src/Drivers/CommunityAdsDriver.php | 89 +++++++++++++++++++ src/Response/CommunityAdsResponse.php | 87 ++++++++++++++++++ stubs/community_ads.env.stub | 5 ++ 6 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 src/Drivers/CommunityAdsDriver.php create mode 100644 src/Response/CommunityAdsResponse.php create mode 100644 stubs/community_ads.env.stub diff --git a/README.md b/README.md index c891121..4909a60 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Latest Version on Packagist](https://img.shields.io/packagist/v/robust-tools/resala.svg?style=flat-square)](https://packagist.org/packages/robust-tools/resala) [![Total Downloads](https://img.shields.io/packagist/dt/robust-tools/resala.svg?style=flat-square)](https://packagist.org/packages/robust-tools/resala) -**Resala** is a PHP & Laravel Package, (Designed to add support to your laravel or just native php app for sending SMS using local operators in the MENA region Like `Vodafone`, `Infobip`, `Connekio`, `VectoryLink`, `Gateway SA`, `BrandEncode`). +**Resala** is a PHP & Laravel Package, (Designed to add support to your laravel or just native php app for sending SMS using local operators in the MENA region Like `Vodafone`, `Infobip`, `Connekio`, `VectoryLink`, `Community Ads`, `Gateway SA`, `BrandEncode`). **Resala** not just tied to use inside Laravel you can hook it up in any php code ## Supported Providers @@ -11,6 +11,7 @@ - Connekio SMS Gateway - Infobip SMS Gateway - Vectory Link SMS Gateway +- Community Ads SMS Gateway - Gateway SA SMS Gateway - BrandEncode SMS Gateway @@ -85,6 +86,14 @@ return [ 'lang' => env('VECTORY_LINK_LANG', 'E') ], + 'community_ads' => [ + 'end_point' => env('COMMUNITY_ADS_END_POINT', 'https://app.community-ads.com/SendSMSAPI/api/SMSSender/SendSMS'), + 'username' => env('COMMUNITY_ADS_USERNAME'), + 'password' => env('COMMUNITY_ADS_PASSWORD'), + 'sender_name' => env('COMMUNITY_ADS_SENDER_NAME', 'Community Ads'), + 'lang' => env('COMMUNITY_ADS_LANG', 'E') + ], + 'gateway_sa' => [ 'end_point' => env('GATEWAYSA_END_POINT', 'http://REST.GATEWAY.SA/api/SendSMS'), 'api_id' => env('GATEWAYSA_API_ID'), @@ -117,6 +126,7 @@ return [ 'connekio' => ConnekioDriver::class, 'infobip' => InfobipDriver::class, 'vectory_link' => VectoryLinkDriver::class, + 'community_ads' => CommunityAdsDriver::class, 'gateway_sa' => GatewaySA::class, 'brandencode' => BrandEncodeDriver::class ], @@ -144,6 +154,11 @@ This adds `vectory_link` environment variables to your .env file. php artisan resala:make vectory_link ``` +This adds `community_ads` environment variables to your .env file. +```bash +php artisan resala:make community_ads +``` + This adds `brandencode` environment variables to your .env file. ```bash php artisan resala:make brandencode diff --git a/config/resala.php b/config/resala.php index af5051a..4d0625f 100644 --- a/config/resala.php +++ b/config/resala.php @@ -5,6 +5,7 @@ use RobustTools\Resala\Drivers\InfobipDriver; use RobustTools\Resala\Drivers\VodafoneDriver; use RobustTools\Resala\Drivers\VectoryLinkDriver; +use RobustTools\Resala\Drivers\CommunityAdsDriver; use RobustTools\Resala\Drivers\BrandEncodeDriver; return [ @@ -58,6 +59,14 @@ 'lang' => env('VECTORY_LINK_LANG', 'E') ], + 'community_ads' => [ + 'end_point' => env('COMMUNITY_ADS_END_POINT', 'https://app.community-ads.com/SendSMSAPI/api/SMSSender/SendSMS'), + 'username' => env('COMMUNITY_ADS_USERNAME'), + 'password' => env('COMMUNITY_ADS_PASSWORD'), + 'sender_name' => env('COMMUNITY_ADS_SENDER_NAME', 'Community Ads'), + 'lang' => env('COMMUNITY_ADS_LANG', 'E') + ], + 'gateway_sa' => [ 'end_point' => env('GATEWAYSA_END_POINT', 'http://REST.GATEWAY.SA/api/SendSMS'), 'api_id' => env('GATEWAYSA_API_ID'), @@ -90,6 +99,7 @@ 'connekio' => ConnekioDriver::class, 'infobip' => InfobipDriver::class, 'vectory_link' => VectoryLinkDriver::class, + 'community_ads' => CommunityAdsDriver::class, 'gateway_sa' => GatewaySA::class, 'brandencode' => BrandEncodeDriver::class ], diff --git a/src/Console/PublishProviderEnvVariablesCommand.php b/src/Console/PublishProviderEnvVariablesCommand.php index 71110b1..be3d5b6 100644 --- a/src/Console/PublishProviderEnvVariablesCommand.php +++ b/src/Console/PublishProviderEnvVariablesCommand.php @@ -82,6 +82,10 @@ private function getStubContent(): string return File::get(__DIR__ . "/../../stubs/vectory_link.env.stub"); } + if ($this->argument('driver') == "community_ads") { + return File::get(__DIR__ . "/../../stubs/community_ads.env.stub"); + } + if ($this->argument('driver') == "brandencode") { return File::get(__DIR__ . "/../../stubs/brandencode.env.stub"); } diff --git a/src/Drivers/CommunityAdsDriver.php b/src/Drivers/CommunityAdsDriver.php new file mode 100644 index 0000000..67255c4 --- /dev/null +++ b/src/Drivers/CommunityAdsDriver.php @@ -0,0 +1,89 @@ +username = $config["username"]; + $this->password = $config["password"]; + $this->senderName = $config["sender_name"]; + $this->endPoint = $config["end_point"]; + $this->lang = $config["lang"]; + } + + /** + * @param string|array $recipients + * @return string|array + */ + public function to($recipients) + { + return $this->recipients = $this->toMultiple($recipients) + ? implode(', ', $recipients) + : $recipients; + } + + public function message(string $message): string + { + return $this->message = $message; + } + + public function send(): SMSDriverResponseInterface + { + return new CommunityAdsResponse(HTTP::post($this->endPoint, $this->headers(), json_encode($this->payload()))); + } + + /** + * @return array + */ + protected function payload(): array + { + return [ + 'SMSText' => $this->message, + 'SMSReceiver' => $this->recipients, + 'SMSSender' => $this->senderName, + 'SMSLang' => $this->lang, + 'UserName' => $this->username, + 'Password' => $this->password, + 'SMSID' => $this->generateGuid(), + ]; + } + + protected function headers(): array + { + return [ + 'Content-Type' => 'application/json', + ]; + } + + private function generateGuid(): string + { + $data = random_bytes(16); + $data[6] = chr(ord($data[6]) & 0x0f | 0x40); + $data[8] = chr(ord($data[8]) & 0x3f | 0x80); + + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } +} diff --git a/src/Response/CommunityAdsResponse.php b/src/Response/CommunityAdsResponse.php new file mode 100644 index 0000000..74f38cf --- /dev/null +++ b/src/Response/CommunityAdsResponse.php @@ -0,0 +1,87 @@ +getBody()->getContents()); + $this->status = $this->parseStatus($contents); + } + + public function success(): bool + { + return $this->status === self::STATUS_SUCCESS; + } + + public function body(): string + { + $messages = [ + self::STATUS_SUCCESS => 'Success', + self::STATUS_INVALID_CREDENTIALS => 'Invalid Credentials', + self::STATUS_INVALID_ACCOUNT_IP => 'Invalid Account IP', + self::STATUS_INVALID_ANI_BLACK_LIST => 'Invalid ANI Black List', + self::STATUS_OUT_OF_CREDIT => 'Out Of Credit', + self::STATUS_DATABASE_DOWN => 'Database Down', + self::STATUS_INACTIVE_ACCOUNT => 'Inactive Account', + self::STATUS_NO_DLR_RECEIVED => 'No DLR received', + self::STATUS_ACCOUNT_EXPIRED => 'Account Is Expired', + self::STATUS_SMS_EMPTY => 'SMS Is Empty', + self::STATUS_INVALID_SENDER_WITH_CONNECTION => 'Invalid Sender With Connection', + self::STATUS_SMS_SENDING_FAILED => 'SMS Sending Failed Try Again', + self::STATUS_USER_CAN_NOT_SEND_WITH_DLR => 'User Can Not Send With DLR', + self::STATUS_OTHER_ERROR => 'Other Error', + self::STATUS_INVALID_ANI => 'Invalid ANI', + self::STATUS_SMS_ID_EXISTS => 'SMS Id Is Exist', + self::STATUS_INVALID_ACCOUNT => 'Invalid Account', + self::STATUS_SMS_NOT_VALIDATE => 'SMS Not Validate', + self::STATUS_INVALID_ACCOUNT_OPERATOR_CONNECTION => 'Invalid Account Operator Connection', + self::STATUS_INVALID_USER_SMS_ID => 'Invalid User SMS Id', + self::STATUS_EMPTY_USERNAME_OR_PASSWORD => 'Empty User Name Or Password', + self::STATUS_INVALID_SENDER => 'Invalid Sender', + self::STATUS_INVALID_START_TIME => 'InvalidStartTime', + self::STATUS_INVALID_SMS_TEMPLATE_OR_ITEMS => 'InvalidSMSTemplateOrItems', + ]; + + return $messages[$this->status] ?? 'Something wrong happened'; + } + + private function parseStatus(string $contents): int + { + if ($contents === '' || !is_numeric($contents)) { + return self::STATUS_OTHER_ERROR; + } + + return (int) $contents; + } +} diff --git a/stubs/community_ads.env.stub b/stubs/community_ads.env.stub new file mode 100644 index 0000000..6245ee4 --- /dev/null +++ b/stubs/community_ads.env.stub @@ -0,0 +1,5 @@ +COMMUNITY_ADS_USERNAME= +COMMUNITY_ADS_PASSWORD= +COMMUNITY_ADS_SENDER_NAME= +COMMUNITY_ADS_END_POINT=https://app.community-ads.com/SendSMSAPI/api/SMSSender/SendSMS +COMMUNITY_ADS_LANG=E