diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index c68765b..9132b11 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: :vendor_name +github: omakei diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 80a788c..b2b96bd 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,14 +1,14 @@ blank_issues_enabled: false contact_links: - name: Ask a question - url: https://github.com/:vendor_name/:package_name/discussions/new?category=q-a + url: https://github.com/omakei/laravel-nextsms/discussions/new?category=q-a about: Ask the community for help - name: Request a feature - url: https://github.com/:vendor_name/:package_name/discussions/new?category=ideas + url: https://github.com/omakei/laravel-nextsms/discussions/new?category=ideas about: Share ideas for new features - name: Report a security issue - url: https://github.com/:vendor_name/:package_name/security/policy + url: https://github.com/omakei/laravel-nextsms/security/policy about: Learn how to notify us for sensitive bugs - name: Report a bug - url: https://github.com/:vendor_name/:package_name/issues/new + url: https://github.com/omakei/laravel-nextsms/issues/new about: Report a reproducable bug diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 12ab7c2..0ceccab 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -1,3 +1,3 @@ # Security Policy -If you discover any security related issues, please email author@domain.com instead of using the issue tracker. +If you discover any security related issues, please email omakei96@gmail.com instead of using the issue tracker. diff --git a/CHANGELOG.md b/CHANGELOG.md index 767365d..ab2a7b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -All notable changes to `:package_name` will be documented in this file. +All notable changes to `laravel-nextsms` will be documented in this file. ## 1.0.0 - 202X-XX-XX diff --git a/LICENSE.md b/LICENSE.md index 58c9ad4..7898534 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) :vendor_name +Copyright (c) omakei Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index b7d5a48..b8567e3 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,236 @@ -# :package_description -[![Latest Version on Packagist](https://img.shields.io/packagist/v/:vendor_slug/:package_slug.svg?style=flat-square)](https://packagist.org/packages/:vendor_slug/:package_slug) -[![GitHub Tests Action Status](https://img.shields.io/github/workflow/status/:vendor_slug/:package_slug/run-tests?label=tests)](https://github.com/:vendor_slug/:package_slug/actions?query=workflow%3Arun-tests+branch%3Amain) -[![GitHub Code Style Action Status](https://img.shields.io/github/workflow/status/:vendor_slug/:package_slug/Check%20&%20fix%20styling?label=code%20style)](https://github.com/:vendor_slug/:package_slug/actions?query=workflow%3A"Check+%26+fix+styling"+branch%3Amain) -[![Total Downloads](https://img.shields.io/packagist/dt/:vendor_slug/:package_slug.svg?style=flat-square)](https://packagist.org/packages/:vendor_slug/:package_slug) - ---- -This repo can be used to scaffold a Laravel package. Follow these steps to get started: +

+ NextSMS Logo +

+# Laravel NextSMS -1. Press the "Use template" button at the top of this repo to create a new repo with the contents of this skeleton -2. Run "php ./configure.php" to run a script that will replace all placeholders throughout all the files -3. Remove this block of text. -4. Have fun creating your package. -5. If you need help creating a package, consider picking up our Laravel Package Training video course. ---- - -This is where your description should go. Limit it to a paragraph or two. Consider adding a small example. +[![Latest Version on Packagist](https://img.shields.io/packagist/v/omakei/laravel-nextsms.svg?style=flat-square)](https://packagist.org/packages/omakei/laravel-nextsms) +[![GitHub Tests Action Status](https://img.shields.io/github/workflow/status/omakei/laravel-nextsms/run-tests?label=tests)](https://github.com/omakei/laravel-nextsms/actions?query=workflow%3Arun-tests+branch%3Amain) +[![GitHub Code Style Action Status](https://img.shields.io/github/workflow/status/omakei/laravel-nextsms/Check%20&%20fix%20styling?label=code%20style)](https://github.com/omakei/laravel-nextsms/actions?query=workflow%3A"Check+%26+fix+styling"+branch%3Amain) +[![Total Downloads](https://img.shields.io/packagist/dt/omakei/laravel-nextsms.svg?style=flat-square)](https://packagist.org/packages/omakei/laravel-nextsms) -## Support us - -[](https://spatie.be/github-ad-click/:package_name) - -We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). - -We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). +Laravel package to send SMS using NextSMS API. ## Installation You can install the package via composer: ```bash -composer require :vendor_slug/:package_slug -``` - -You can publish and run the migrations with: - -```bash -php artisan vendor:publish --tag=":package_slug-migrations" -php artisan migrate +composer require omakei/laravel-nextsms ``` You can publish the config file with: ```bash -php artisan vendor:publish --tag=":package_slug-config" +php artisan vendor:publish --tag="laravel-nextsms-config" ``` -Optionally, you can publish the views using +The following keys must be available in your `.env` file: ```bash -php artisan vendor:publish --tag=":package_slug-views" +NEXTSMS_USERNAME= +NEXTSMS_PASSWORD= +NEXTSMS_SENDER_ID= ``` -This is the contents of the published config file: +This is the contents of the published `config` file: ```php return [ + 'username' => env('NEXTSMS_USERNAME', 'NEXTSMS'), + 'password' => env('NEXTSMS_PASSWORD', 'NEXTSMS'), + 'api_key' => base64_encode(env('NEXTSMS_USERNAME', 'NEXTSMS').':'.env('NEXTSMS_PASSWORD', 'NEXTSMS')), + 'sender_id' => env('NEXTSMS_SENDER_ID', 'NEXTSMS'), + 'url' => [ + 'sms' => [ + 'single' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/text/single', + 'multiple' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/text/multi', + 'reports' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/reports', + 'logs' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/logs', + 'balance' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/balance', + ], + 'sub_customer' => [ + 'create' => NextSMS::NEXTSMS_BASE_URL.'/api/reseller/v1/sub_customer/create', + 'recharge' => NextSMS::NEXTSMS_BASE_URL.'/api/reseller/v1/sub_customer/recharge', + 'deduct' => NextSMS::NEXTSMS_BASE_URL.'/api/reseller/v1/sub_customer/deduct', + ] + ], ]; ``` ## Usage +### Send SMS + +Sending single sms to single destination: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::sendSingleSMS(['to' => '255625933171', 'text' => 'Dj Omakei is texting.']); + +``` + +Sending single sms to multiple destinations: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::sendSingleSMSToMultipleDestination([ + 'to' => ['255625933171','255656699895'], + 'text' => 'Dj Omakei is texting.']); + +``` + +Sending multiple sms to multiple destinations (Example 1): + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::sendMultipleSMSToMultipleDestinations(['messages' => [ + ['to' => '255625933171', 'text' => 'Dj Omakei is texting.'], + ['to' => '255656699895', 'text' => 'Dj Omakei is texting.'] + ]]); + +``` + +Sending multiple sms to multiple destinations (Example 2): + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::sendMultipleSMSToMultipleDestinations(['messages' => [ + ['to' => ['255625933171','255656699895'], 'text' => 'Dj Omakei is texting.'], + ['to' => '255625933171', 'text' => 'Dj Omakei is texting.'] + ]]); + +``` + +Schedule sms: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::scheduleSMS([ + 'to' => '255625933171', + 'text' => 'Dj Omakei is texting.', + 'date' => '2022-01-25' , + 'time' => '12:00']); + +``` + +### SMS Delivery Reports + +Get all delivery reports: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::getAllDeliveryReports(); + +``` + +Get delivery reports with messageId: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::getDeliveryReportWithMessageId(243452542526627); + +``` + +Get delivery reports with messageId: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::getDeliveryReportWithSpecificDateRange('2022-01-25', '2022-01-29'); + +``` + +### Sent Sms Logs + +Get all sent SMS logs: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::getAllSentSMSLogs(10, 5); + +``` + +Get all sent SMS logs with the optional parameter: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::getAllSentSMSLogsWithOptionalParameter('255625933171','2022-01-25', '2022-01-29',10, 5); + +``` + +### Sub Customer + +Register Sub Customer: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::subCustomerCreate( + 'Michael', + 'Omakei', + 'omakei', + 'omakei96@gmail.com', + '06259313171', + 'Sub Customer (Reseller)', + 100); + +``` + +Recharge customer: + ```php -$skeleton = new VendorName\Skeleton(); -echo $skeleton->echoPhrase('Hello, VendorName!'); + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::subCustomerRecharge('omakei96@gmail.com', 100); + ``` +Deduct a customer: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::subCustomerDeduct('omakei96@gmail.com', 100); + +``` + +Get sms balance: + +```php + +use Omakei\NextSMS\NextSMS; + +$response = NextSMS::getSMSBalance(); + +``` + +## NextSMS API Documentation + +Please see [NextSMS Developer API](https://documenter.getpostman.com/view/4680389/SW7dX7JL#2936eed4-6027-45e7-92c9-fe1cd7df140b) for more details. + ## Testing ```bash @@ -86,7 +251,7 @@ Please review [our security policy](../../security/policy) on how to report secu ## Credits -- [:author_name](https://github.com/:author_username) +- [omakei](https://github.com/omakei) - [All Contributors](../../contributors) ## License diff --git a/art/nextsms-logo.png b/art/nextsms-logo.png new file mode 100644 index 0000000..5a6c9ee Binary files /dev/null and b/art/nextsms-logo.png differ diff --git a/composer.json b/composer.json index 1ffdef8..866935a 100644 --- a/composer.json +++ b/composer.json @@ -1,17 +1,17 @@ { - "name": ":vendor_slug/:package_slug", - "description": ":package_description", + "name": "omakei/laravel-nextsms", + "description": "A Laravel package to send SMS using NextSMS API ", "keywords": [ - ":vendor_name", + "omakei", "laravel", - ":package_slug" + "laravel-nextsms" ], - "homepage": "https://github.com/:vendor_slug/:package_slug", + "homepage": "https://github.com/omakei/laravel-nextsms", "license": "MIT", "authors": [ { - "name": ":author_name", - "email": "author@domain.com", + "name": "omakei", + "email": "omakei96@gmail.com", "role": "Developer" } ], @@ -26,6 +26,7 @@ "orchestra/testbench": "^6.22", "pestphp/pest": "^1.21", "pestphp/pest-plugin-laravel": "^1.1", + "pestphp/pest-plugin-mock": "^1.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", @@ -34,13 +35,13 @@ }, "autoload": { "psr-4": { - "VendorName\\Skeleton\\": "src", - "VendorName\\Skeleton\\Database\\Factories\\": "database/factories" + "Omakei\\NextSMS\\": "src", + "Omakei\\NextSMS\\Database\\Factories\\": "database/factories" } }, "autoload-dev": { "psr-4": { - "VendorName\\Skeleton\\Tests\\": "tests" + "Omakei\\NextSMS\\Tests\\": "tests" } }, "scripts": { @@ -54,10 +55,10 @@ "extra": { "laravel": { "providers": [ - "VendorName\\Skeleton\\SkeletonServiceProvider" + "Omakei\\NextSMS\\NextSMSServiceProvider" ], "aliases": { - "Skeleton": "VendorName\\Skeleton\\Facades\\Skeleton" + "NextSMS": "Omakei\\NextSMS\\Facades\\NextSMS" } } }, diff --git a/config/nextsms.php b/config/nextsms.php new file mode 100644 index 0000000..f0af9a4 --- /dev/null +++ b/config/nextsms.php @@ -0,0 +1,25 @@ + env('NEXTSMS_USERNAME', 'NEXTSMS'), + 'password' => env('NEXTSMS_PASSWORD', 'NEXTSMS'), + 'api_key' => base64_encode(env('NEXTSMS_USERNAME', 'NEXTSMS').':'.env('NEXTSMS_PASSWORD', 'NEXTSMS')), + 'sender_id' => env('NEXTSMS_SENDER_ID', 'NEXTSMS'), + 'url' => [ + 'sms' => [ + 'single' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/text/single', + 'multiple' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/text/multi', + 'reports' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/reports', + 'logs' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/logs', + 'balance' => NextSMS::NEXTSMS_BASE_URL.'/api/sms/v1/balance', + ], + 'sub_customer' => [ + 'create' => NextSMS::NEXTSMS_BASE_URL.'/api/reseller/v1/sub_customer/create', + 'recharge' => NextSMS::NEXTSMS_BASE_URL.'/api/reseller/v1/sub_customer/recharge', + 'deduct' => NextSMS::NEXTSMS_BASE_URL.'/api/reseller/v1/sub_customer/deduct', + ] + ], +]; diff --git a/config/skeleton.php b/config/skeleton.php deleted file mode 100644 index fbb0e4c..0000000 --- a/config/skeleton.php +++ /dev/null @@ -1,5 +0,0 @@ - $version) { - if (in_array($name, $names, true)) { - unset($data['require-dev'][$name]); - } - } - - file_put_contents(__DIR__.'/composer.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); -} - -function remove_composer_script($scriptName) { - $data = json_decode(file_get_contents(__DIR__.'/composer.json'), true); - - foreach($data['scripts'] as $name => $script) { - if ($scriptName === $name) { - unset($data['scripts'][$name]); - break; - } - } - - file_put_contents(__DIR__.'/composer.json', json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); -} - -function remove_readme_paragraphs(string $file): void { - $contents = file_get_contents($file); - - file_put_contents( - $file, - preg_replace('/.*/s', '', $contents) ?: $contents - ); -} - -function safeUnlink(string $filename) { - if (file_exists($filename) && is_file($filename)) { - unlink($filename); - } -} - -function determineSeparator(string $path): string { - return str_replace('/', DIRECTORY_SEPARATOR, $path); -} - -function replaceForWindows(): array { - return preg_split('/\\r\\n|\\r|\\n/', run('dir /S /B * | findstr /v /i .git\ | findstr /v /i vendor | findstr /v /i '.basename(__FILE__).' | findstr /r /i /M /F:/ ":author :vendor :package VendorName skeleton vendor_name vendor_slug author@domain.com"')); -} - -function replaceForAllOtherOSes(): array { - return explode(PHP_EOL, run('grep -E -r -l -i ":author|:vendor|:package|VendorName|skeleton|vendor_name|vendor_slug|author@domain.com" --exclude-dir=vendor ./* ./.github/* | grep -v ' . basename(__FILE__))); -} - -$gitName = run('git config user.name'); -$authorName = ask('Author name', $gitName); - -$gitEmail = run('git config user.email'); -$authorEmail = ask('Author email', $gitEmail); - -$usernameGuess = explode(':', run('git config remote.origin.url'))[1]; -$usernameGuess = dirname($usernameGuess); -$usernameGuess = basename($usernameGuess); -$authorUsername = ask('Author username', $usernameGuess); - -$vendorName = ask('Vendor name', $authorUsername); -$vendorSlug = slugify($vendorName); -$vendorNamespace = ucwords($vendorName); -$vendorNamespace = ask('Vendor namespace', $vendorNamespace); - -$currentDirectory = getcwd(); -$folderName = basename($currentDirectory); - -$packageName = ask('Package name', $folderName); -$packageSlug = slugify($packageName); -$packageSlugWithoutPrefix = remove_prefix('laravel-', $packageSlug); - -$className = title_case($packageName); -$className = ask('Class name', $className); -$description = ask('Package description', "This is my package {$packageSlug}"); - -$usePhpStan = confirm('Enable PhpStan?', true); -$usePhpCsFixer = confirm('Enable PhpCsFixer?', true); -$useUpdateChangelogWorkflow = confirm('Use automatic changelog updater workflow?', true); - -writeln('------'); -writeln("Author : {$authorName} ({$authorUsername}, {$authorEmail})"); -writeln("Vendor : {$vendorName} ({$vendorSlug})"); -writeln("Package : {$packageSlug} <{$description}>"); -writeln("Namespace : {$vendorNamespace}\\{$className}"); -writeln("Class name : {$className}"); -writeln("---"); -writeln("Packages & Utilities"); -writeln("Use PhpCsFixer : " . ($usePhpCsFixer ? 'yes' : 'no')); -writeln("Use Larastan/PhpStan : " . ($usePhpStan ? 'yes' : 'no')); -writeln("Use Auto-Changelog : " . ($useUpdateChangelogWorkflow ? 'yes' : 'no')); -writeln('------'); - -writeln('This script will replace the above values in all relevant files in the project directory.'); - -if (! confirm('Modify files?', true)) { - exit(1); -} - -$files = (str_starts_with(strtoupper(PHP_OS), 'WIN') ? replaceForWindows() : replaceForAllOtherOSes()); - -foreach ($files as $file) { - replace_in_file($file, [ - ':author_name' => $authorName, - ':author_username' => $authorUsername, - 'author@domain.com' => $authorEmail, - ':vendor_name' => $vendorName, - ':vendor_slug' => $vendorSlug, - 'VendorName' => $vendorNamespace, - ':package_name' => $packageName, - ':package_slug' => $packageSlug, - ':package_slug_without_prefix' => $packageSlugWithoutPrefix, - 'Skeleton' => $className, - 'skeleton' => $packageSlug, - ':package_description' => $description, - ]); - - match (true) { - str_contains($file, determineSeparator('src/Skeleton.php')) => rename($file, determineSeparator('./src/' . $className . '.php')), - str_contains($file, determineSeparator('src/SkeletonServiceProvider.php')) => rename($file, determineSeparator('./src/' . $className . 'ServiceProvider.php')), - str_contains($file, determineSeparator('src/Facades/Skeleton.php')) => rename($file, determineSeparator('./src/Facades/' . $className . '.php')), - str_contains($file, determineSeparator('src/Commands/SkeletonCommand.php')) => rename($file, determineSeparator('./src/Commands/' . $className . 'Command.php')), - str_contains($file, determineSeparator('database/migrations/create_skeleton_table.php.stub')) => rename($file, determineSeparator('./database/migrations/create_' . $packageSlugWithoutPrefix . '_table.php.stub')), - str_contains($file, determineSeparator('config/skeleton.php')) => rename($file, determineSeparator('./config/' . $packageSlugWithoutPrefix . '.php')), - str_contains($file, 'README.md') => remove_readme_paragraphs($file), - default => [], - }; -} - -if (! $usePhpCsFixer) { - safeUnlink(__DIR__ . '/.php_cs.dist.php'); - safeUnlink(__DIR__ . '/.github/workflows/php-cs-fixer.yml'); -} - -if (! $usePhpStan) { - safeUnlink(__DIR__ . '/phpstan.neon.dist'); - safeUnlink(__DIR__ . '/phpstan-baseline.neon'); - safeUnlink(__DIR__ . '/.github/workflows/phpstan.yml'); - - remove_composer_deps([ - 'phpstan/extension-installer', - 'phpstan/phpstan-deprecation-rules', - 'phpstan/phpstan-phpunit', - 'nunomaduro/larastan', - ]); - - remove_composer_script('phpstan'); -} - -if (! $useUpdateChangelogWorkflow) { - safeUnlink(__DIR__ . '/.github/workflows/update-changelog.yml'); -} - -confirm('Execute `composer install` and run tests?') && run('composer install && composer test'); - -confirm('Let this script delete itself?', true) && unlink(__FILE__); diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index c51604f..51f128f 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -1,6 +1,6 @@ id(); // add fields diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 3bbe22a..513924a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -19,7 +19,7 @@ verbose="true" > - + tests diff --git a/src/Commands/SkeletonCommand.php b/src/Commands/NextSMSCommand.php similarity index 63% rename from src/Commands/SkeletonCommand.php rename to src/Commands/NextSMSCommand.php index 3e5f628..761f87e 100644 --- a/src/Commands/SkeletonCommand.php +++ b/src/Commands/NextSMSCommand.php @@ -1,12 +1,12 @@ $messageId]); + } + + public static function getDeliveryReportWithSpecificDateRange(string $sentSince, string $sentUntil): Response + { + throw_if(count(explode('-', $sentSince))!=3 || count(explode('-', $sentUntil))!=3 + , InvalidPayload::invalidPayloadArrayKeyType('"date" key of format "YYYY-MM-DD"')); + + $dateSince = explode('-', $sentSince); + + $dateUnit = explode('-', $sentUntil); + + throw_if(checkdate($dateSince[1], $dateSince[2],$dateSince[0]) || + checkdate($dateUnit[1], $dateUnit[2],$dateUnit[0]) + , InvalidPayload::invalidPayloadArrayKeyType('"date" key of format "YYYY-MM-DD"')); + + return self::makeGetRequest(config('nextsms.url.sms.reports'), + ['sentSince' => $sentSince, 'sentUntil' => $sentUntil]); + } + + public static function getAllSentSMSLogs(int $limit, int $offset): Response + { + return self::makeGetRequest(config('nextsms.url.sms.reports'), [ + 'from' => config('nextsms.sender_id'), + 'limit' => $limit, + 'offset' => $offset + ]); + } + + public static function getAllSentSMSLogsWithOptionalParameter( + string $to, string $sentSince, string $sentUntil, int $limit, int $offset): Response + { + + throw_if(count(explode('-', $sentSince))!=3 || count(explode('-', $sentUntil))!=3 + , InvalidPayload::invalidPayloadArrayKeyType('"date" key of format "YYYY-MM-DD"')); + + $dateSince = explode('-', $sentSince); + + $dateUnit = explode('-', $sentUntil); + + throw_if(checkdate($dateSince[1], $dateSince[2],$dateSince[0]) || + checkdate($dateUnit[1], $dateUnit[2],$dateUnit[0]) + , InvalidPayload::invalidSingleSMSPayload()); + + + return self::makeGetRequest(config('nextsms.url.sms.reports'), [ + 'from' => config('nextsms.sender_id'), + 'to' => $to, + 'sentSince' => $sentSince, + 'sentUntil' => $sentUntil, + 'limit' => $limit, + 'offset' => $offset + ]); + } + + public static function getSMSBalance(): Response + { + return self::makeGetRequest(config('nextsms.url.sms.balance'), []); + } + + public static function subCustomerCreate( + string $first_name, + string $last_name, + string $username, + string $email, + string $phone_number, + string $account_type, + int $sms_price): Response + { + + throw_if($account_type !='Sub Customer' || + $account_type !='Sub Customer (Reseller)' + , InvalidPayload::invalidAccountType()); + + return self::makePostRequest(config('nextsms.url.sub_customer.create'), [ + 'first_name'=> $first_name, + 'last_name'=> $last_name, + 'username'=> $username, + 'email'=> $email, + 'phone_number'=> $phone_number, + 'account_type'=> $account_type, + 'sms_price'=> $sms_price + ]); + } + + public static function subCustomerRecharge(string $email, int $smscount): Response + { + return self::makePostRequest(config('nextsms.url.sub_customer.recharge'), [ + 'email'=> $email, + 'smscount'=> $smscount + ]); + } + + + public static function subCustomerDeduct(string $email, int $smscount): Response + { + return self::makePostRequest(config('nextsms.url.sub_customer.deduct'), [ + 'email'=> $email, + 'smscount'=> $smscount + ]); + } + + protected static function makePostRequest(string $url, mixed $payload): Response + { + return Http::withHeaders(self::getHeaders())->post($url, $payload); + } + + protected static function makeGetRequest(string $url, mixed $payload): Response + { + return Http::withHeaders(self::getHeaders())->get($url, $payload); + + } + + protected static function getHeaders(): array + { + return [ + 'Authorization' => 'Basic ' . config('nextsms.api_key'), + 'Content-Type' => 'application/json', + 'Accept' => 'application/json', + ]; + } + + protected static function getSingleSMSPayload(array $payload): array + { + throw_if(count(array_diff(['to','text'], array_keys($payload))) != 0, + InvalidPayload::invalidSingleSMSPayload()); + + return array_merge(['from' => config('textsms.sender_id'), $payload]); + + } + + protected static function getSingleSMSToMultipleDestinationPayload(array $payload): array + { + throw_if(count(array_diff(['to','text'], array_keys($payload))) != 0, + InvalidPayload::invalidSingleSMSPayload()); + + throw_if(!is_array($payload['to']), InvalidPayload::invalidMultipleSMSPayload()); + + return array_merge(['from' => config('textsms.sender_id'), $payload]); + + } + + protected static function getMultipleSMSToMultipleDestinationPayload(array $payload): array + { + throw_if(count(array_diff(['messages'], array_keys($payload))) != 0, + InvalidPayload::invalidPayloadArrayKeys('"messages"')); + + throw_if(!is_array($payload['messages']), + InvalidPayload::invalidPayloadArrayKeyType('"messages" key of type array')); + + + $payloads = []; + $index = 0; + + foreach ($payload['messages'] as $object) + { + throw_if(count(array_diff(['to','text'], array_keys($object))) != 0, + InvalidPayload::invalidSingleSMSPayload()); + + throw_if(!is_array(array_column($object, 'to')) || + !is_string(array_column($object, 'to')), + InvalidPayload::invalidPayloadArrayKeyType('"to" key of type array or "to" key of type string')); + + + $payloads['messages'][$index] = array_merge(['from' => config('textsms.sender_id'), $object]); + + $index++; + } + + return $payloads; + + } + + protected static function getScheduleSMSPayload(array $payload): array + { + throw_if(count(array_diff(['to','text', 'date', 'time'], array_keys($payload))) != 0, + InvalidPayload::invalidPayloadArrayKeys('"to", "text", "date" and "time"')); + + throw_if(count(explode('-', $payload['date']))!=3, + InvalidPayload::invalidPayloadArrayKeyType('"date" key of format "YYYY-MM-DD"')); + + throw_if(count(explode(':', $payload['time']))!=2, + InvalidPayload::invalidPayloadArrayKeyType('"time" key of format "HH:MM"')); + + $date = explode('-', $payload['date']); + + throw_if(!checkdate($date[1], $date[2],$date[0]), + InvalidPayload::invalidPayloadArrayKeyType('"date" key of format "YYYY-MM-DD"')); + + throw_if(!preg_match("/(2[0-3]|[0][0-9]|1[0-9]):([0-5][0-9])/", $payload['time']), + InvalidPayload::invalidPayloadArrayKeyType('"time" key of format "HH:MM"')); + + return array_merge(['from' => config('textsms.sender_id'), $payload]); + + } + +} diff --git a/src/SkeletonServiceProvider.php b/src/NextSMSServiceProvider.php similarity index 59% rename from src/SkeletonServiceProvider.php rename to src/NextSMSServiceProvider.php index 618b267..9b71a4a 100644 --- a/src/SkeletonServiceProvider.php +++ b/src/NextSMSServiceProvider.php @@ -1,12 +1,12 @@ name('skeleton') + ->name('laravel-nextsms') ->hasConfigFile() ->hasViews() - ->hasMigration('create_skeleton_table') - ->hasCommand(SkeletonCommand::class); + ->hasMigration('create_laravel-nextsms_table') + ->hasCommand(NextSMSCommand::class); } } diff --git a/src/Skeleton.php b/src/Skeleton.php deleted file mode 100755 index 66fab60..0000000 --- a/src/Skeleton.php +++ /dev/null @@ -1,7 +0,0 @@ -toBeTrue(); -}); diff --git a/tests/NextSMSTest.php b/tests/NextSMSTest.php new file mode 100644 index 0000000..67d9892 --- /dev/null +++ b/tests/NextSMSTest.php @@ -0,0 +1,341 @@ + + Http::response( $stub, 200)]); + + $response = NextSMS::sendSingleSMS(['to' => '25576328997', 'text' => 'Dj Omakei is texting.']); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_throw_exception_when_payload_of_single_destination_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The payload provided must contain "to" and "text" keys.'); + + $response = NextSMS::sendSingleSMS(['to' => '25576328997']); + + } + + /** @test */ + public function it_can_send_single_sms_to_multiple_destination() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/multiple_destination.json'), + true); + + Http::fake([config('nextsms.url.sms.single') => + Http::response( $stub, 200)]); + + $response = NextSMS::sendSingleSMSToMultipleDestination([ + 'to' => ['25576328997'], + 'text' => 'Dj Omakei is texting.']); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_throw_exception_when_payload_of_multiple_destination_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The payload provided must contain "to" key of type array.'); + + $response = NextSMS::sendSingleSMSToMultipleDestination([ + 'to' => '25576328997', + 'text' => 'Dj Omakei is texting.']); + + } + + /** @test */ + public function it_can_send_multiple_sms_to_multiple_destination() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/multiple_sms_to_multiple_destination.json'), + true); + + Http::fake([config('nextsms.url.sms.multiple') => + Http::response( $stub , 200)]); + + $response = NextSMS::sendMultipleSMSToMultipleDestinations(['messages' => [[ + 'to' => '25576328997', + 'text' => 'Dj Omakei is texting.']]]); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_throw_exception_when_payload_of_multiple_sms_to_multiple_destination_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The payload provided must contain "to" and "text" keys.'); + + $response = NextSMS::sendMultipleSMSToMultipleDestinations(['messages' =>[ + ['to' => '25576328997']]]); + + } + + /** @test */ + public function it_can_schedule_sms() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/schedule_sms.json'), + true); + + Http::fake([config('nextsms.url.sms.single') => + Http::response( $stub , 200)]); + + $response = NextSMS::scheduleSMS([ + 'to' => '25576328997', + 'text' => 'Dj Omakei is texting.', + 'date' => '2022-01-25' , + 'time' => '12:00' + ]); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_throw_exception_when_date_payload_of_schedule_sms_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The payload provided must contain "date" key of format "YYYY-MM-DD".'); + + $response = NextSMS::scheduleSMS([ + 'to' => '25576328997', + 'text' => 'Dj Omakei is texting.', + 'date' => '2022/01/25' , + 'time' => '12:00' + ]); + + } + + /** @test */ + public function it_can_throw_exception_when_time_payload_of_schedule_sms_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The payload provided must contain "time" key of format "HH:MM".'); + + $response1 = NextSMS::scheduleSMS([ + 'to' => '25576328997', + 'text' => 'Dj Omakei is texting.', + 'date' => '2022-01-25' , + 'time' => '12:90' + ]); + + + } + + /** @test */ + public function it_can_get_all_delivery_reports() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/recharge_sub_customer.json'), + true); + + Http::fake([config('nextsms.url.sms.reports') => + Http::response( $stub , 200)]); + + $response = NextSMS::getAllDeliveryReports(); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_delivery_report_with_message_id() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/delivery_reports_with_message_id.json'), + true); + + Http::fake([config('nextsms.url.sms.reports') => + Http::response( $stub , 200)]); + + $response = NextSMS::getDeliveryReportWithMessageId(2346673573733); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_get_delivery_report_with_specific_date_range() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/delivery_report_with_specific_date_range.json'), + true); + + Http::fake([config('nextsms.url.sms.reports') => + Http::response( $stub , 200)]); + + $response = NextSMS::getDeliveryReportWithSpecificDateRange('2022-01-25', '2022-01-29'); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_throw_exception_when_arguments_of_get_delivery_report_with_specific_date_range_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The payload provided must contain "date" key of format "YYYY-MM-DD".'); + + $response = NextSMS::getDeliveryReportWithSpecificDateRange('2022/01/25', '2022/01/29'); + + } + + /** @test */ + public function it_can_get_all_sent_sms_logs() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/all_sent_sms_logs.json'), + true); + + Http::fake([config('nextsms.url.sms.reports') => + Http::response( $stub, 200)]); + + $response = NextSMS::getAllSentSMSLogs(20,5); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_get_all_sent_sms_logs_with_optional_parameter() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/all_sent_sms_logs.json'), + true); + + Http::fake([config('nextsms.url.sms.reports') => + Http::response( $stub , 200)]); + + $response = NextSMS::getAllSentSMSLogsWithOptionalParameter( + '255625933171','2022-01-25', '2022-01-29',10, 5); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_throw_exception_when_arguments_of_get_all_sent_sms_logs_with_optional_parameter_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The payload provided must contain "date" key of format "YYYY-MM-DD".'); + + $response = NextSMS::getAllSentSMSLogsWithOptionalParameter( + '255625933171','2022/01/25', '2022/01/29',10, 5); + + + } + + /** @test */ + public function it_can_get_sms_balance() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/get_sms_balance.json'), + true); + + Http::fake([config('nextsms.url.sms.balance') => + Http::response( $stub , 200)]); + + $response = NextSMS::getSMSBalance(); + + $this->assertEquals($response, $stub); + } + + + /** @test */ + public function it_can_register_sub_customer() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/create_sub_customer.json'), + true); + + Http::fake([config('nextsms.url.sub_customer.create') => + Http::response( $stub , 200)]); + + $response = NextSMS::subCustomerCreate( 'Michael', + 'Omakei', + 'omakei', + 'omakei96@gmail.com', + '06259313171', + 'Sub Customer (Reseller)', + 100); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_throw_exception_when_arguments_of_register_sub_customer_is_invalid() { + + $this->expectException(InvalidPayload::class); + + $this->expectExceptionMessage('The account type must be Sub Customer or Sub Customer (Reseller).'); + + $response = NextSMS::subCustomerCreate( 'Michael', + 'Omakei', + 'omakei', + 'omakei96@gmail.com', + '06259313171', + 'Sub Customer (Omakei)', + 100); + + } + + /** @test */ + public function it_can_recharge_sub_customer() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/recharge_sub_customer.json'), + true); + + Http::fake([config('nextsms.url.sub_customer.recharge') => + Http::response( $stub , 200)]); + + $response = NextSMS::subCustomerRecharge('omakei96@gmail.com', 100); + + $this->assertEquals($response, $stub); + } + + /** @test */ + public function it_can_deduct_sub_customer() { + + $stub = json_decode( + file_get_contents(__DIR__ . '/stubs/responses/deduct_sub_customer.json'), + true); + + Http::fake([config('nextsms.url.sub_customer.deduct') => + Http::response( $stub, 200)]); + + $response = NextSMS::subCustomerDeduct('omakei96@gmail.com', 100); + + $this->assertEquals($response, $stub); + } +} + diff --git a/tests/Pest.php b/tests/Pest.php index 7fe1500..c6d6c3d 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,5 +1,5 @@ in(__DIR__); diff --git a/tests/TestCase.php b/tests/TestCase.php index d04fb0c..72febbc 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,10 +1,10 @@ 'VendorName\\Skeleton\\Database\\Factories\\'.class_basename($modelName).'Factory' + fn (string $modelName) => 'Omakei\\NextSMS\\Database\\Factories\\'.class_basename($modelName).'Factory' ); } protected function getPackageProviders($app) { return [ - SkeletonServiceProvider::class, + NextSMSServiceProvider::class, ]; } @@ -29,7 +29,7 @@ public function getEnvironmentSetUp($app) config()->set('database.default', 'testing'); /* - $migration = include __DIR__.'/../database/migrations/create_skeleton_table.php.stub'; + $migration = include __DIR__.'/../database/migrations/create_laravel-nextsms_table.php.stub'; $migration->up(); */ } diff --git a/tests/stubs/responses/all_delivery_reports.json b/tests/stubs/responses/all_delivery_reports.json new file mode 100644 index 0000000..4bd03b3 --- /dev/null +++ b/tests/stubs/responses/all_delivery_reports.json @@ -0,0 +1,57 @@ +{ + "results": [ + { + "messageId": "2808579298410163167", + "sentAt": "2020-02-08 12:28:51", + "doneAt": "2020-04-21 18:23:07", + "to": "255716718040", + "smsCount": 1, + "status": { + "groupId": 3, + "groupName": "DELIVERED", + "id": 5, + "name": "DELIVERED_TO_HANDSET", + "description": "Message delivered to handset" + }, + "error": { + "groupId": 0, + "groupName": "OK", + "id": 0, + "name": "NO_ERROR", + "description": "No Error", + "permanent": false + } + }, + { + "messageId": "28227686813403535606", + "sentAt": "2020-02-21 12:21:00", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "smsCount": 1, + "status": null, + "error": null + }, + { + "messageId": "28089492984101631440", + "sentAt": "2020-02-05 12:28:51", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "smsCount": 1, + "status": { + "groupId": 3, + "groupName": "DELIVERED", + "id": 5, + "name": "DELIVERED_TO_HANDSET", + "description": "Message delivered to handset" + }, + "error": { + "groupId": 0, + "groupName": "OK", + "id": 0, + "name": "NO_ERROR", + "description": "No Error", + "permanent": false + } + } + ] +} diff --git a/tests/stubs/responses/all_sent_sms_logs.json b/tests/stubs/responses/all_sent_sms_logs.json new file mode 100644 index 0000000..b4a489b --- /dev/null +++ b/tests/stubs/responses/all_sent_sms_logs.json @@ -0,0 +1,62 @@ +{ + "results": [ + { + "messageId": "28695733526003536021", + "sentAt": "2020-04-15 16:09:00", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "from": "NEXTSMS", + "text": "test", + "smsCount": 1, + "status": { + "groupId": 1, + "groupName": "PENDING", + "id": 7, + "name": "PENDING_ENROUTE", + "description": "Message sent to next instance" + }, + "error": null + }, + { + "messageId": "28255409354101630625", + "sentAt": "2020-02-24 17:21:00", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "from": "NEXTSMS", + "text": "test", + "smsCount": 1, + "status": { + "groupId": 5, + "groupName": "REJECTED", + "id": 12, + "name": "REJECTED_NOT_ENOUGH_CREDITS", + "description": "Not enough credits" + }, + "error": null + }, + { + "messageId": "28089492984101631440", + "sentAt": "2020-02-05 12:28:51", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "from": "NEXTSMS", + "text": "Your message", + "smsCount": 1, + "status": { + "groupId": 3, + "groupName": "DELIVERED", + "id": 5, + "name": "DELIVERED_TO_HANDSET", + "description": "Message delivered to handset" + }, + "error": { + "groupId": 0, + "groupName": "OK", + "id": 0, + "name": "NO_ERROR", + "description": "No Error", + "permanent": false + } + } + ] +} diff --git a/tests/stubs/responses/all_sent_sms_logs_with_optional_parameters.json b/tests/stubs/responses/all_sent_sms_logs_with_optional_parameters.json new file mode 100644 index 0000000..8b04d55 --- /dev/null +++ b/tests/stubs/responses/all_sent_sms_logs_with_optional_parameters.json @@ -0,0 +1,28 @@ +{ + "results": [ + { + "messageId": "28089492984101631440", + "sentAt": "2020-02-05 12:28:51", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "from": "NEXTSMS", + "text": "Your message", + "smsCount": 1, + "status": { + "groupId": 3, + "groupName": "DELIVERED", + "id": 5, + "name": "DELIVERED_TO_HANDSET", + "description": "Message delivered to handset" + }, + "error": { + "groupId": 0, + "groupName": "OK", + "id": 0, + "name": "NO_ERROR", + "description": "No Error", + "permanent": false + } + } + ] +} diff --git a/tests/stubs/responses/create_sub_customer.json b/tests/stubs/responses/create_sub_customer.json new file mode 100644 index 0000000..35c8b7d --- /dev/null +++ b/tests/stubs/responses/create_sub_customer.json @@ -0,0 +1,13 @@ +{ + "success": true, + "status": 200, + "message": "Customer created successfully. Email is sent to your customer email address for confirmation.", + "result": { + "name": "Api Customer", + "username": "apicust", + "phone_number": "+255738234339", + "email": "apicust@customer.com", + "account_type": "Sub Customer (Reseller)", + "sms_price": "20.00 TSH" + } +} diff --git a/tests/stubs/responses/deduct_sub_customer.json b/tests/stubs/responses/deduct_sub_customer.json new file mode 100644 index 0000000..0dec123 --- /dev/null +++ b/tests/stubs/responses/deduct_sub_customer.json @@ -0,0 +1,11 @@ +{ + "success": true, + "status": 200, + "message": "Transaction completed successfully", + "result": { + "Customer": "example@email.com", + "Sms deducted": 2000, + "Your sms balance": 470000, + "Customer sms balance": 3000 + } +} diff --git a/tests/stubs/responses/delivery_report_with_specific_date_range.json b/tests/stubs/responses/delivery_report_with_specific_date_range.json new file mode 100644 index 0000000..0641732 --- /dev/null +++ b/tests/stubs/responses/delivery_report_with_specific_date_range.json @@ -0,0 +1,26 @@ +{ + "results": [ + { + "messageId": "28089492984101631440", + "sentAt": "2020-02-05 12:28:51", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "smsCount": 1, + "status": { + "groupId": 3, + "groupName": "DELIVERED", + "id": 5, + "name": "DELIVERED_TO_HANDSET", + "description": "Message delivered to handset" + }, + "error": { + "groupId": 0, + "groupName": "OK", + "id": 0, + "name": "NO_ERROR", + "description": "No Error", + "permanent": false + } + } + ] +} diff --git a/tests/stubs/responses/delivery_reports_with_message_id.json b/tests/stubs/responses/delivery_reports_with_message_id.json new file mode 100644 index 0000000..0641732 --- /dev/null +++ b/tests/stubs/responses/delivery_reports_with_message_id.json @@ -0,0 +1,26 @@ +{ + "results": [ + { + "messageId": "28089492984101631440", + "sentAt": "2020-02-05 12:28:51", + "doneAt": "2020-04-18 18:23:07", + "to": "255716718040", + "smsCount": 1, + "status": { + "groupId": 3, + "groupName": "DELIVERED", + "id": 5, + "name": "DELIVERED_TO_HANDSET", + "description": "Message delivered to handset" + }, + "error": { + "groupId": 0, + "groupName": "OK", + "id": 0, + "name": "NO_ERROR", + "description": "No Error", + "permanent": false + } + } + ] +} diff --git a/tests/stubs/responses/get_sms_balance.json b/tests/stubs/responses/get_sms_balance.json new file mode 100644 index 0000000..d835987 --- /dev/null +++ b/tests/stubs/responses/get_sms_balance.json @@ -0,0 +1,3 @@ +{ + "sms_balance": 5 +} diff --git a/tests/stubs/responses/multiple_destination.json b/tests/stubs/responses/multiple_destination.json new file mode 100644 index 0000000..df174c3 --- /dev/null +++ b/tests/stubs/responses/multiple_destination.json @@ -0,0 +1,26 @@ +{ + "messages": [ + { + "to": "255655912841", + "status": { + "groupId": 1, + "groupName": "PENDING", + "id": 7, + "name": "PENDING_ENROUTE", + "description": "Message sent to next instance" + }, + "smsCount": 1 + }, + { + "to": "255716718040", + "status": { + "groupId": 1, + "groupName": "PENDING", + "id": 7, + "name": "PENDING_ENROUTE", + "description": "Message sent to next instance" + }, + "smsCount": 1 + } + ] +} diff --git a/tests/stubs/responses/multiple_sms_to_multiple_destination.json b/tests/stubs/responses/multiple_sms_to_multiple_destination.json new file mode 100644 index 0000000..2b28b4b --- /dev/null +++ b/tests/stubs/responses/multiple_sms_to_multiple_destination.json @@ -0,0 +1,26 @@ +{ + "messages": [ + { + "to": "255716718040", + "status": { + "groupId": 1, + "groupName": "PENDING", + "id": 7, + "name": "PENDING_ENROUTE", + "description": "Message sent to next instance" + }, + "smsCount": 1 + }, + { + "to": "255655912841", + "status": { + "groupId": 1, + "groupName": "PENDING", + "id": 7, + "name": "PENDING_ENROUTE", + "description": "Message sent to next instance" + }, + "smsCount": 1 + } + ] +} diff --git a/tests/stubs/responses/recharge_sub_customer.json b/tests/stubs/responses/recharge_sub_customer.json new file mode 100644 index 0000000..c65b19d --- /dev/null +++ b/tests/stubs/responses/recharge_sub_customer.json @@ -0,0 +1,10 @@ +{ + "success": true, + "status": 200, + "message": "Transaction completed successfully", + "result": { + "Customer": "example@email.com", + "Sms transferred": 5000, + "Your sms balance": 450000 + } +} diff --git a/tests/stubs/responses/schedule_sms.json b/tests/stubs/responses/schedule_sms.json new file mode 100644 index 0000000..b38de9d --- /dev/null +++ b/tests/stubs/responses/schedule_sms.json @@ -0,0 +1,15 @@ +{ + "messages": [ + { + "to": "255716718040", + "status": { + "groupId": 1, + "groupName": "PENDING", + "id": 26, + "name": "PENDING_ACCEPTED", + "description": "Pending accepted , will be sent on scheduled time." + }, + "smsCount": 1 + } + ] +} diff --git a/tests/stubs/responses/single_destination.json b/tests/stubs/responses/single_destination.json new file mode 100644 index 0000000..671447d --- /dev/null +++ b/tests/stubs/responses/single_destination.json @@ -0,0 +1,15 @@ +{ + "messages": [ + { + "to": "255716718040", + "status": { + "groupId": 1, + "groupName": "PENDING", + "id": 7, + "name": "PENDING_ENROUTE", + "description": "Message sent to next instance" + }, + "smsCount": 1 + } + ] +}