diff --git a/CHANGELOG.md b/CHANGELOG.md
index dfb68ae..625d037 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,12 @@
All notable changes to `netgsm` will be documented in this file
+## 2.0.0 - 2020-03-02
+
+- namespaces and folder structure changed
+- available credit and packages service added
+- tests updated
+
## 1.0.1 - 2020-02-17
- default sms sending method changed to get
@@ -10,4 +16,3 @@ All notable changes to `netgsm` will be documented in this file
## 1.0.0 - 2020-02-17
- initial release
-
diff --git a/README.md b/README.md
index d2271e8..b0f5cff 100755
--- a/README.md
+++ b/README.md
@@ -19,6 +19,9 @@ Also, this package provides simple reporting.
- [Available SMS Interfaces](#available-sms-interfaces)
- [Reporting](#reporting)
- [Available Reporting Interfaces](#available-report-interfaces)
+ - [Account Balance](#account-balance)
+ - [Remaining Balance](#remaining-balance)
+ - [Remaining Package Credits](#remaining-package-credits)
- [Testing](#testing)
- [Security](#security)
- [Contributing](#contributing)
@@ -225,6 +228,73 @@ Report Results
| total | All | No | Yes
+### Account Balance
+
+With this service, you can inquire the remaining balance of your netgsm account and the credit balances of your packages.
+
+#### Remaining Balance
+
+Returns the remaining money balance on netgsm account. (TL)
+
+Usage:
+
+```php
+Netgsm::getCredit();
+```
+
+Output:
+
+```php
+2,7
+```
+
+#### Remaining Package Credits
+
+Returns the credit balances of the packages defined in the relevant netgsm account.
+
+Usage:
+
+```php
+Netgsm::getAvailablePackages();
+```
+
+Output:
+
+```php
+class Illuminate\Support\Collection#105 (1) {
+ protected $items =>
+ array(3) {
+ [0] =>
+ array(3) {
+ 'amount' =>
+ int(1000)
+ 'amountType' =>
+ string(14) "Adet Flash Sms"
+ 'packageType' =>
+ string(0) ""
+ }
+ [1] =>
+ array(3) {
+ 'amount' =>
+ int(953)
+ 'amountType' =>
+ string(12) "Adet OTP Sms"
+ 'packageType' =>
+ string(0) ""
+ }
+ [2] =>
+ array(3) {
+ 'amount' =>
+ int(643)
+ 'amountType' =>
+ string(4) "Adet"
+ 'packageType' =>
+ string(3) "SMS"
+ }
+ }
+}
+```
+
### Testing
``` bash
diff --git a/config/config.php b/config/config.php
index 8544778..48f29e9 100755
--- a/config/config.php
+++ b/config/config.php
@@ -9,5 +9,7 @@
'language' => env('NETGSM_LANGUAGE', 'tr'),
'header' => env('NETGSM_HEADER', null),
'sms_sending_method' => env('NETGSM_SMS_SENDING_METHOD', 'get'),
+ 'base_uri' => env('NETGSM_BASE_URI', 'https://api.netgsm.com.tr'),
+ 'timeout' => env('NETGSM_TIMEOUT', 60),
],
];
diff --git a/src/Balance/NetgsmAvailableCredit.php b/src/Balance/NetgsmAvailableCredit.php
new file mode 100644
index 0000000..8e45817
--- /dev/null
+++ b/src/Balance/NetgsmAvailableCredit.php
@@ -0,0 +1,75 @@
+ NetgsmErrors::CREDENTIALS_INCORRECT,
+ '40' => NetgsmErrors::CREDENTIALS_INCORRECT,
+ '100' => NetgsmErrors::SYSTEM_ERROR,
+ ];
+
+ /**
+ * extracts credit from the returned response.
+ *
+ * @return string
+ * @throws NetgsmException
+ */
+ public function parseResponse(): ?string
+ {
+ $result = explode(' ', $this->response);
+
+ if (empty($result[0])) {
+ throw new NetgsmException(NetgsmErrors::NETGSM_GENERAL_ERROR);
+ }
+
+ $code = $result[0];
+
+ if (! in_array($code, $this->successCodes)) {
+ $message = $this->errorCodes[$code];
+ throw new NetgsmException($message, $code);
+ }
+
+ return $result[1];
+ }
+
+ /**
+ * returns the credits amount for associated netgsm account.
+ *
+ * @throws NetgsmErrors
+ * @throws GuzzleException
+ * @throws NetgsmException
+ */
+ public function getCredit(): ?string
+ {
+ $this->response = $this->callApi('GET', $this->url);
+
+ return $this->parseResponse();
+ }
+}
diff --git a/src/Balance/NetgsmPackages.php b/src/Balance/NetgsmPackages.php
new file mode 100644
index 0000000..7ea7288
--- /dev/null
+++ b/src/Balance/NetgsmPackages.php
@@ -0,0 +1,73 @@
+ NetgsmErrors::MESSAGE_TOO_LONG,
+ '40' => NetgsmErrors::CREDENTIALS_INCORRECT,
+ '100' => NetgsmErrors::SYSTEM_ERROR,
+ ];
+
+ /**
+ * handles the response and return the package list as an array.
+ *
+ * @return array
+ * @throws NetgsmException
+ */
+ public function parseResponse(): array
+ {
+ $availablePackages = [];
+
+ if (array_key_exists($this->response, $this->errorCodes)) {
+ $message = $this->errorCodes[$this->response];
+ throw new NetgsmException($message, $this->response);
+ }
+
+ $rows = array_filter(explode('
', $this->response));
+ foreach ($rows as $row) {
+ $columns = array_filter(explode('|', $row));
+ $columns = array_map('trim', $columns);
+ $availablePackages[] = [
+ 'amount' => (int) $columns[0],
+ 'amountType' => $columns[1] ?? null,
+ 'packageType' => $columns[2] ?? null,
+ ];
+ }
+
+ return $availablePackages;
+ }
+
+ /**
+ * returns the packages list for associated netgsm account.
+ *
+ * @return array
+ * @throws GuzzleException
+ * @throws NetgsmException
+ */
+ public function getPackages(): array
+ {
+ $this->response = $this->callApi('GET', $this->url, ['tip' => 1]);
+
+ return $this->parseResponse();
+ }
+}
diff --git a/src/Exceptions/CouldNotSendNotification.php b/src/Exceptions/CouldNotSendNotification.php
index ee20762..6f9e4b1 100644
--- a/src/Exceptions/CouldNotSendNotification.php
+++ b/src/Exceptions/CouldNotSendNotification.php
@@ -2,22 +2,11 @@
namespace TarfinLabs\Netgsm\Exceptions;
+use Exception;
use GuzzleHttp\Exception\ClientException;
-class CouldNotSendNotification extends \Exception
+class CouldNotSendNotification extends Exception
{
- const MESSAGE_TOO_LONG = 'Mesaj metnindeki bir problemden dolayı gönderilemedi veya standart maksimum mesaj karakter sayısını geçtiniz.';
- const START_DATE_INCORRECT = 'Mesaj gönderim baslangıç tarihinde hata var. Sistem tarihi ile değiştirilip işleme alındı.';
- const END_DATE_INCORRECT = 'Mesaj gönderim sonlandırılma tarihinde hata var. Sistem tarihi ile değiştirilip işleme alındı.Bitiş tarihi başlangıç tarihinden küçük girilmiş ise, sistem bitiş tarihine içinde bulunduğu tarihe 24 saat ekler.';
- const SENDER_INCORRECT = 'Mesaj başlığınız (gönderici adınızın) sistemde tanımlı değil.';
- const CREDENTIALS_INCORRECT = 'Geçersiz kullanıcı adı, şifre veya kullanıcınızın API erişim izni yok.';
- const PARAMETERS_INCORRECT = 'Hatalı sorgulama. Gönderdiğiniz parametrelerden birisi hatalı veya zorunlu alanlardan biri eksik.';
- const RECEIVER_INCORRECT = 'Gönderilen numara hatalı.';
- const OTP_ACCOUNT_NOT_DEFINED = 'Hesabınızda OTP SMS Paketi tanımlı değildir.';
- const QUERY_LIMIT_EXCEED = 'Hesabınızda OTP SMS Paketi tanımlı değildir.';
- const SYSTEM_ERROR = 'Sistem hatası.';
- const NETGSM_GENERAL_ERROR = 'Netgsm responded with an error :';
-
/**
* Thrown when there's a bad request and an error is responded.
*
diff --git a/src/Exceptions/IncorrectPhoneNumberFormatException.php b/src/Exceptions/IncorrectPhoneNumberFormatException.php
index 90e28d5..030de9e 100644
--- a/src/Exceptions/IncorrectPhoneNumberFormatException.php
+++ b/src/Exceptions/IncorrectPhoneNumberFormatException.php
@@ -2,6 +2,8 @@
namespace TarfinLabs\Netgsm\Exceptions;
-class IncorrectPhoneNumberFormatException extends \Exception
+use Exception;
+
+class IncorrectPhoneNumberFormatException extends Exception
{
}
diff --git a/src/Exceptions/InvalidConfiguration.php b/src/Exceptions/InvalidConfiguration.php
index 36bb13f..f95999e 100644
--- a/src/Exceptions/InvalidConfiguration.php
+++ b/src/Exceptions/InvalidConfiguration.php
@@ -11,6 +11,6 @@ class InvalidConfiguration extends Exception
*/
public static function configurationNotSet()
{
- return new static('In order to send notification via netgsm you need to add credentials in the `netgsm` key of `config.services`.');
+ return new static('In order to send notification via netgsm you need to add credentials in the `credentials` key of `config.netgsm`.');
}
}
diff --git a/src/Exceptions/NetgsmException.php b/src/Exceptions/NetgsmException.php
new file mode 100644
index 0000000..47f46b3
--- /dev/null
+++ b/src/Exceptions/NetgsmException.php
@@ -0,0 +1,9 @@
+getReports();
}
+
+ /**
+ * Returns the remaining credits amount (TL) on the netgsm account.
+ *
+ * @return string
+ * @throws Exceptions\NetgsmException
+ * @throws GuzzleException
+ */
+ public function getCredit()
+ {
+ $creditService = new NetgsmAvailableCredit();
+ $creditService->setClient($this->client);
+ $creditService->setCredentials($this->credentials);
+
+ return $creditService->getCredit();
+ }
+
+ /**
+ * Returns the available package list and their balances on the netgsm account.
+ *
+ * @return array
+ * @throws Exceptions\NetgsmException
+ * @throws GuzzleException
+ */
+ public function getAvailablePackages(): Collection
+ {
+ $packageService = new NetgsmPackages();
+ $packageService->setClient($this->client);
+ $packageService->setCredentials($this->credentials);
+
+ return collect($packageService->getPackages());
+ }
}
diff --git a/src/NetgsmApiClient.php b/src/NetgsmApiClient.php
new file mode 100644
index 0000000..e219fb5
--- /dev/null
+++ b/src/NetgsmApiClient.php
@@ -0,0 +1,81 @@
+client = $client;
+
+ return $this;
+ }
+
+ /**
+ * @param array $credentials
+ * @return $this
+ */
+ public function setCredentials(array $credentials): self
+ {
+ $this->credentials = $credentials;
+
+ return $this;
+ }
+
+ /**
+ * Sends requests to netgsm api endpoints with specified credentials.
+ *
+ * @param $method
+ * @param $url
+ * @param null $params
+ * @param array $headers
+ * @return string
+ * @throws GuzzleException
+ */
+ protected function callApi($method, $url, $params = null, $headers = [])
+ {
+ $options = [
+ 'query' => [
+ 'usercode' => $this->credentials['user_code'],
+ 'password' => $this->credentials['secret'],
+ ],
+ ];
+
+ if ($method == 'POST') {
+ if (is_array($params)) {
+ $options['form_params'] = $params;
+ } else {
+ $options['body'] = $params;
+ }
+ }
+
+ if ($method == 'GET' && is_array($params)) {
+ $options['query'] = array_merge($options['query'], $params);
+ }
+
+ if ($headers) {
+ $options['headers'] = $headers;
+ }
+
+ $response = $this->client->request($method, $url, $options);
+
+ return $response->getBody()->getContents();
+ }
+}
diff --git a/src/NetgsmChannel.php b/src/NetgsmChannel.php
index 28bad5f..ec9a2c9 100644
--- a/src/NetgsmChannel.php
+++ b/src/NetgsmChannel.php
@@ -2,7 +2,11 @@
namespace TarfinLabs\Netgsm;
+use Exception;
+use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Notifications\Notification;
+use TarfinLabs\Netgsm\Exceptions\IncorrectPhoneNumberFormatException;
+use TarfinLabs\Netgsm\Sms\AbstractNetgsmMessage;
class NetgsmChannel
{
@@ -19,15 +23,15 @@ public function __construct(Netgsm $netgsm)
* @param $notifiable
* @param Notification $notification
* @throws Exceptions\CouldNotSendNotification
- * @throws Exceptions\IncorrectPhoneNumberFormatException
- * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws GuzzleException
+ * @throws IncorrectPhoneNumberFormatException
*/
public function send($notifiable, Notification $notification)
{
$message = $notification->toNetgsm($notifiable);
if (! $message instanceof AbstractNetgsmMessage) {
- throw new \Exception('Geçerli bir Netgsm mesajı değil');
+ throw new Exception('Geçerli bir Netgsm mesajı değil');
}
$phone = $notifiable->routeNotificationFor('Netgsm');
diff --git a/src/NetgsmErrors.php b/src/NetgsmErrors.php
new file mode 100644
index 0000000..824a7fb
--- /dev/null
+++ b/src/NetgsmErrors.php
@@ -0,0 +1,22 @@
+ $config['defaults']['base_uri'],
+ 'timeout' => $config['defaults']['timeout'],
+ ]);
+
+ return new Netgsm($client, $config['credentials'], $config['defaults']);
});
}
}
diff --git a/src/AbstractNetgsmReport.php b/src/Report/AbstractNetgsmReport.php
similarity index 79%
rename from src/AbstractNetgsmReport.php
rename to src/Report/AbstractNetgsmReport.php
index e7f2f49..4d66f2e 100644
--- a/src/AbstractNetgsmReport.php
+++ b/src/Report/AbstractNetgsmReport.php
@@ -1,13 +1,14 @@
credentials = $credentials;
-
- return $this;
- }
-
- /**
- * @param ClientInterface $client
- * @return AbstractNetgsmReport
- */
- public function setClient(ClientInterface $client): self
- {
- $this->client = $client;
-
- return $this;
- }
-
/**
* @param string $type
* @return AbstractNetgsmReport
@@ -159,6 +129,8 @@ public function setPage(int $page): self
}
/**
+ * formats the value by specified type.
+ *
* @param $value
* @param $format
* @return int|string
@@ -178,15 +150,15 @@ protected function formatValue($value, $format)
}
/**
+ * returns the netgsm basic sms reports as a collection.
+ *
* @return Collection
- * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws GuzzleException
* @throws ReportException
*/
public function getReports(): Collection
{
$data = [
- 'usercode' => $this->credentials['user_code'],
- 'password' => $this->credentials['secret'],
'page' => 1,
];
@@ -194,11 +166,7 @@ public function getReports(): Collection
$keep = true;
$allResults = new Collection();
do {
- $queryStr = http_build_query($data);
-
- $rawResponse = $this->client->request('GET', $this->url.'?'.$queryStr)
- ->getBody()
- ->getContents();
+ $rawResponse = $this->callApi('GET', $this->url, $data);
if ($this->paginated) {
if (in_array($rawResponse, $this->noResultCodes)) {
@@ -219,6 +187,8 @@ public function getReports(): Collection
}
/**
+ * validates the response returned from netgsm report api.
+ *
* @param $response
* @return bool
* @throws ReportException
diff --git a/src/NetgsmSmsDetailReport.php b/src/Report/NetgsmSmsDetailReport.php
similarity index 92%
rename from src/NetgsmSmsDetailReport.php
rename to src/Report/NetgsmSmsDetailReport.php
index 2198f7e..a8cd619 100644
--- a/src/NetgsmSmsDetailReport.php
+++ b/src/Report/NetgsmSmsDetailReport.php
@@ -1,6 +1,6 @@
fields), array_filter($this->mappers()));
}
- /**
- * @param mixed $client
- * @return AbstractNetgsmMessage
- */
- public function setClient(ClientInterface $client): self
- {
- $this->client = $client;
-
- return $this;
- }
-
/**
* @param array $defaults
* @return AbstractNetgsmMessage
@@ -283,17 +281,6 @@ public function setDefaults(array $defaults): self
return $this;
}
- /**
- * @param array $credentials
- * @return AbstractNetgsmMessage
- */
- public function setCredentials(array $credentials): self
- {
- $this->credentials = $credentials;
-
- return $this;
- }
-
/**
* @param Carbon $startDate
* @return AbstractNetgsmMessage
@@ -316,14 +303,6 @@ public function setEndDate(Carbon $endDate): self
return $this;
}
- /**
- * @return string
- */
- protected function getResponseContent(): string
- {
- return $this->response->getBody()->getContents();
- }
-
/**
* @return mixed
*/
@@ -333,15 +312,17 @@ public function getJobId(): string
}
/**
+ * parses the response from api and returns job id.
+ *
* @return $this
* @throws CouldNotSendNotification
*/
public function parseResponse(): self
{
- $result = explode(' ', $this->getResponseContent());
+ $result = explode(' ', $this->response);
if (! isset($result[0])) {
- throw new CouldNotSendNotification(CouldNotSendNotification::NETGSM_GENERAL_ERROR);
+ throw new CouldNotSendNotification(NetgsmErrors::NETGSM_GENERAL_ERROR);
}
if (! in_array($result[0], self::SUCCESS_CODES)) {
@@ -356,44 +337,40 @@ public function parseResponse(): self
}
/**
+ * sends a sms via get method.
+ *
* @return $this
* @throws CouldNotSendNotification
- * @throws IncorrectPhoneNumberFormatException
- * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws GuzzleException
*/
protected function sendViaGet(): self
{
- $query = http_build_query($this->body());
-
- $this->response = $this->client->request('GET', $this->getUrl().'?'.$query);
+ $this->response = $this->callApi('GET', $this->getUrl(), $this->body());
return $this->parseResponse();
}
/**
+ * sends a sms via xml method.
+ *
* @return $this
* @throws CouldNotSendNotification
- * @throws \GuzzleHttp\Exception\GuzzleException
+ * @throws GuzzleException
*/
protected function sendViaXml(): self
{
- $options = [
- 'headers' => [
- 'Content-Type' => 'text/xml; charset=UTF8',
- ],
- 'body' => $this->createXmlPost(),
- ];
-
- $this->response = $this->client->request('POST', $this->getUrl(), $options);
+ $this->response = $this->callApi('POST', $this->getUrl(), $this->createXmlPost(), [
+ 'Content-Type' => 'text/xml; charset=UTF8',
+ ]);
return $this->parseResponse();
}
/**
+ * sends a sms via specified sending method.
+ *
* @return $this
- * @throws CouldNotSendNotification
* @throws IncorrectPhoneNumberFormatException
- * @throws \GuzzleHttp\Exception\GuzzleException
*/
public function send()
{
diff --git a/src/NetgsmOtpMessage.php b/src/Sms/NetgsmOtpMessage.php
similarity index 63%
rename from src/NetgsmOtpMessage.php
rename to src/Sms/NetgsmOtpMessage.php
index 6d8b965..4d3e099 100644
--- a/src/NetgsmOtpMessage.php
+++ b/src/Sms/NetgsmOtpMessage.php
@@ -1,33 +1,33 @@
CouldNotSendNotification::MESSAGE_TOO_LONG,
- '30' => CouldNotSendNotification::CREDENTIALS_INCORRECT,
- '40' => CouldNotSendNotification::SENDER_INCORRECT,
- '50' => CouldNotSendNotification::RECEIVER_INCORRECT,
- '60' => CouldNotSendNotification::OTP_ACCOUNT_NOT_DEFINED,
- '70' => CouldNotSendNotification::PARAMETERS_INCORRECT,
- '80' => CouldNotSendNotification::QUERY_LIMIT_EXCEED,
- '100' => CouldNotSendNotification::SYSTEM_ERROR,
+ '20' => NetgsmErrors::MESSAGE_TOO_LONG,
+ '30' => NetgsmErrors::CREDENTIALS_INCORRECT,
+ '40' => NetgsmErrors::SENDER_INCORRECT,
+ '50' => NetgsmErrors::RECEIVER_INCORRECT,
+ '60' => NetgsmErrors::OTP_ACCOUNT_NOT_DEFINED,
+ '70' => NetgsmErrors::PARAMETERS_INCORRECT,
+ '80' => NetgsmErrors::QUERY_LIMIT_EXCEED,
+ '100' => NetgsmErrors::SYSTEM_ERROR,
];
protected $fields = [
- 'usercode',
- 'password',
'msgheader',
'msg',
'no',
];
/**
+ * creates the xml request body for sms sending via xml post method.
+ *
* @return string
*/
protected function createXmlPost(): string
@@ -61,13 +61,13 @@ public function getUrl(): string
}
/**
+ * maps the given parameters according to the required parameters of the otp message endpoint.
+ *
* @return array
*/
protected function mappers(): array
{
return [
- 'usercode' => $this->credentials['user_code'],
- 'password' => $this->credentials['secret'],
'msgheader' => $this->header ?? $this->defaults['header'],
'msg' => $this->message,
'no' => is_array($this->recipients) ? $this->recipients[0] : $this->recipients,
diff --git a/src/NetgsmSmsMessage.php b/src/Sms/NetgsmSmsMessage.php
similarity index 75%
rename from src/NetgsmSmsMessage.php
rename to src/Sms/NetgsmSmsMessage.php
index 6c2ad02..71eaed9 100644
--- a/src/NetgsmSmsMessage.php
+++ b/src/Sms/NetgsmSmsMessage.php
@@ -1,23 +1,21 @@
CouldNotSendNotification::MESSAGE_TOO_LONG,
- '30' => CouldNotSendNotification::CREDENTIALS_INCORRECT,
- '40' => CouldNotSendNotification::SENDER_INCORRECT,
- '70' => CouldNotSendNotification::PARAMETERS_INCORRECT,
+ '20' => NetgsmErrors::MESSAGE_TOO_LONG,
+ '30' => NetgsmErrors::CREDENTIALS_INCORRECT,
+ '40' => NetgsmErrors::SENDER_INCORRECT,
+ '70' => NetgsmErrors::PARAMETERS_INCORRECT,
];
protected $fields = [
- 'usercode',
- 'password',
'gsmno',
'message',
'msgheader',
@@ -28,6 +26,7 @@ class NetgsmSmsMessage extends AbstractNetgsmMessage
];
/**
+ * creates the xml request body for sms sending via xml post method.
* @return string
*/
protected function createXmlPost(): string
@@ -55,13 +54,16 @@ protected function createXmlPost(): string
return $xml;
}
+ /**
+ * maps the given parameters according to the required parameters of the sms message endpoint.
+ *
+ * @return array
+ */
protected function mappers(): array
{
return [
'gsmno' => implode(',', $this->recipients),
'msgheader' => $this->header ?? $this->defaults['header'],
- 'usercode' => $this->credentials['user_code'],
- 'password' => $this->credentials['secret'],
'message' => $this->message,
'startdate' => ! empty($this->startDate) ? $this->startDate->format('dmYHi') : null,
'stopdate' => ! empty($this->endDate) ? $this->endDate->format('dmYHi') : null,
diff --git a/tests/NetGsmChannelTest.php b/tests/NetGsmChannelTest.php
index 00b4986..48048a8 100644
--- a/tests/NetGsmChannelTest.php
+++ b/tests/NetGsmChannelTest.php
@@ -43,8 +43,8 @@ public function setUp(): void
$this->notifiable = new TestNotifiable;
$this->netgsm = Mockery::mock(new Netgsm($this->httpClient, [
- 'userCode' => '',
- 'secret' => '',
+ 'user_code' => '',
+ 'secret' => '',
]));
$this->channel = new NetGsmChannel($this->netgsm);
diff --git a/tests/NetGsmMessageTest.php b/tests/NetGsmMessageTest.php
index 39281d1..e559330 100644
--- a/tests/NetGsmMessageTest.php
+++ b/tests/NetGsmMessageTest.php
@@ -2,7 +2,7 @@
namespace TarfinLabs\Netgsm\Tests;
-use TarfinLabs\Netgsm\NetgsmSmsMessage;
+use TarfinLabs\Netgsm\Sms\NetgsmSmsMessage;
class NetGsmMessageTest extends BaseTestCase
{
diff --git a/tests/NetGsmReportDetailTest.php b/tests/NetGsmReportDetailTest.php
index fb8c61f..5dd4876 100644
--- a/tests/NetGsmReportDetailTest.php
+++ b/tests/NetGsmReportDetailTest.php
@@ -10,7 +10,7 @@
use SimpleXMLElement;
use TarfinLabs\Netgsm\Exceptions\ReportException;
use TarfinLabs\Netgsm\Netgsm;
-use TarfinLabs\Netgsm\NetgsmSmsDetailReport;
+use TarfinLabs\Netgsm\Report\NetgsmSmsDetailReport;
class NetGsmReportDetailTest extends BaseTestCase
{
diff --git a/tests/NetGsmReportTest.php b/tests/NetGsmReportTest.php
index 4db14e5..cf683e2 100644
--- a/tests/NetGsmReportTest.php
+++ b/tests/NetGsmReportTest.php
@@ -9,7 +9,7 @@
use Mockery;
use TarfinLabs\Netgsm\Exceptions\ReportException;
use TarfinLabs\Netgsm\Netgsm;
-use TarfinLabs\Netgsm\NetgsmSmsReport;
+use TarfinLabs\Netgsm\Report\NetgsmSmsReport;
class NetGsmReportTest extends BaseTestCase
{
diff --git a/tests/NetGsmTest.php b/tests/NetGsmTest.php
index 3dfc00e..ea1c596 100644
--- a/tests/NetGsmTest.php
+++ b/tests/NetGsmTest.php
@@ -8,7 +8,7 @@
use TarfinLabs\Netgsm\Exceptions\CouldNotSendNotification;
use TarfinLabs\Netgsm\Exceptions\IncorrectPhoneNumberFormatException;
use TarfinLabs\Netgsm\Netgsm;
-use TarfinLabs\Netgsm\NetgsmSmsMessage;
+use TarfinLabs\Netgsm\Sms\NetgsmSmsMessage;
class NetGsmTest extends BaseTestCase
{
diff --git a/tests/NetgsmAvailableCreditTest.php b/tests/NetgsmAvailableCreditTest.php
new file mode 100644
index 0000000..126f323
--- /dev/null
+++ b/tests/NetgsmAvailableCreditTest.php
@@ -0,0 +1,77 @@
+httpClient = Mockery::mock(new Client());
+
+ $this->netgsm = new Netgsm($this->httpClient, [
+ 'user_code' => $this->faker->userName,
+ 'secret' => $this->faker->password,
+ ]);
+ }
+
+ /**
+ * @param $response
+ */
+ protected function mockCreditApiRequest($response)
+ {
+ $this->httpClient->shouldReceive('request')
+ ->andReturn(new Response(
+ $status = 200,
+ $headers = [],
+ $response
+ ));
+ }
+
+ /**
+ * @test
+ */
+ public function it_get_available_credit_balance_with_correct_arguments()
+ {
+ $credit = $this->faker->numberBetween(5, 10);
+
+ $response = '00 '.$credit;
+
+ $this->mockCreditApiRequest($response);
+
+ $response = $this->netgsm->getCredit();
+
+ $this->assertSame((string) $credit, $response);
+ }
+
+ /**
+ * @test
+ */
+ public function should_throw_exception_when_return_code_is_not_success()
+ {
+ $errorCode = $this->faker->randomElement([30, 40, 100]);
+ $this->mockCreditApiRequest($errorCode);
+
+ $this->expectException(NetgsmException::class);
+ $this->expectExceptionCode($errorCode);
+
+ $this->netgsm->getCredit();
+ }
+}
diff --git a/tests/NetgsmAvailablePackagesTest.php b/tests/NetgsmAvailablePackagesTest.php
new file mode 100644
index 0000000..e6f1549
--- /dev/null
+++ b/tests/NetgsmAvailablePackagesTest.php
@@ -0,0 +1,80 @@
+httpClient = Mockery::mock(new Client());
+
+ $this->netgsm = new Netgsm($this->httpClient, [
+ 'user_code' => $this->faker->userName,
+ 'secret' => $this->faker->password,
+ ]);
+ }
+
+ /**
+ * @param $response
+ */
+ protected function mockCreditApiRequest($response)
+ {
+ $this->httpClient->shouldReceive('request')
+ ->andReturn(new Response(
+ $status = 200,
+ $headers = [],
+ $response
+ ));
+ }
+
+ /**
+ * @test
+ */
+ public function it_get_available_package_amounts_with_correct_arguments()
+ {
+ $response = '1000 | Adet Flash Sms |
953 | Adet OTP Sms |
643 | Adet | SMS
';
+
+ $this->mockCreditApiRequest($response);
+
+ $response = $this->netgsm->getAvailablePackages();
+
+ $this->assertSame($response[0]['amount'], 1000);
+ $this->assertSame($response[0]['amountType'], 'Adet Flash Sms');
+ $this->assertSame($response[1]['amount'], 953);
+ $this->assertSame($response[1]['amountType'], 'Adet OTP Sms');
+ $this->assertSame($response[2]['amount'], 643);
+ $this->assertSame($response[2]['amountType'], 'Adet');
+ }
+
+ /**
+ * @test
+ */
+ public function should_throw_exception_when_return_code_is_not_success()
+ {
+ $errorCode = $this->faker->randomElement([30, 40, 100]);
+ $this->mockCreditApiRequest($errorCode);
+
+ $this->expectException(NetgsmException::class);
+ $this->expectExceptionCode($errorCode);
+
+ $this->netgsm->getAvailablePackages();
+ }
+}
diff --git a/tests/notification/TestNotification.php b/tests/notification/TestNotification.php
index 121e7a2..ec39839 100644
--- a/tests/notification/TestNotification.php
+++ b/tests/notification/TestNotification.php
@@ -3,7 +3,7 @@
namespace TarfinLabs\Netgsm\Tests\notification;
use Illuminate\Notifications\Notification;
-use TarfinLabs\Netgsm\NetgsmSmsMessage;
+use TarfinLabs\Netgsm\Sms\NetgsmSmsMessage;
class TestNotification extends Notification
{