diff --git a/README.md b/README.md old mode 100644 new mode 100755 index c631fe5..817c8aa --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ The following providers are supported: * [CardBoardFish](http://www.cardboardfish.com/) * [ValueFirst](http://vfirst.com/) (only covering India's networks) * [Swisscom](http://developer.swisscom.com/) (based on the [GSMA OneAPI](http://www.gsma.com/oneapi/) Specification) +* [websms](https://websms.at/) Installation ------------ diff --git a/src/SmsSender/Provider/WebsmsProvider.php b/src/SmsSender/Provider/WebsmsProvider.php new file mode 100755 index 0000000..2821c74 --- /dev/null +++ b/src/SmsSender/Provider/WebsmsProvider.php @@ -0,0 +1,163 @@ + + * @see + */ +class WebsmsProvider extends AbstractProvider +{ + /** + * @var string + */ + const ENDPOINT_URL = 'https://api.websms.com/rest/smsmessaging/text'; + + /** + * @var string + */ + protected $accessToken; + + /** + * @var string + */ + protected $internationalPrefix; + + /** + * {@inheritDoc} + */ + public function __construct(HttpAdapterInterface $adapter, $accessToken, $internationalPrefix = '+43') + { + parent::__construct($adapter); + + $this->accessToken = $accessToken; + $this->internationalPrefix = $internationalPrefix; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'websms'; + } + + /** + * {@inheritDoc} + */ + public function send($recipient, $body, $originator = '') + { + if (null === $this->accessToken) { + throw new Exception\InvalidCredentialsException('No API credentials provided'); + } + + $params = array( + 'messageContent' => $body, + 'recipientAddressList' => array( + $this->removeLeadingPlusIfPresent( + $this->localNumberToInternational($recipient, $this->internationalPrefix) + ) + ) + ); + + return $this->executeQuery(self::ENDPOINT_URL, $params, array( + 'recipient' => $recipient, + 'body' => $body, + 'originator' => $originator, + )); + } + + /** + * Issues the actual HTTP query. + * + * @param $url + * @param array $data + * @param array $extra_result_data + * @return array + */ + protected function executeQuery($url, array $data = array(), array $extra_result_data = array()) + { + $headers = array( + sprintf('Authorization: Bearer %s', $this->accessToken), + 'Content-Type: application/json', + 'Accept: application/json' + ); + + // Issue the request + $content = $this->getAdapter()->getContent($url, 'POST', $headers, json_encode($data)); + + if (null === $content) { + return array_merge($this->getDefaults(), $extra_result_data); + } + + return $this->parseResults($content, $extra_result_data); + } + + /** + * Parses the data returned by the API. + * + * @param string $result The raw result string. + * @return array + */ + protected function parseResults($result, array $extra_result_data = array()) + { + $data = json_decode($result, true); + $smsData = array(); + + // There was an error + if (empty($data['transferId']) || empty($data['statusCode'])) { + return array_merge($this->getDefaults(), $extra_result_data, array( + 'status' => ResultInterface::STATUS_FAILED, + ) + ); + } + + // Get the transfer id + $smsData['id'] = $data['transferId']; + + // Get the status + switch ($data['statusCode']) { + case 2000: + $smsData['status'] = ResultInterface::STATUS_SENT; + break; + case 2001: + $smsData['status'] = ResultInterface::STATUS_QUEUED; + break; + default: + $smsData['status'] = ResultInterface::STATUS_FAILED; + break; + } + + return array_merge($this->getDefaults(), $extra_result_data, $smsData); + } + + /** + * Removes the leading plus sign from the international phone number as websms requires it that way. + * + * @param string $number The number to strip the plus sign from + * @return string + */ + protected function removeLeadingPlusIfPresent($number) + { + if ($number[0] !== '+') { + // The number has no leading "+" sign + return $number; + } else { + + // Remove the leading "+" sign and add the prefix + return substr($number, 1); + } + } +} diff --git a/tests/SmsSender/Tests/Provider/WebsmsProviderTest.php b/tests/SmsSender/Tests/Provider/WebsmsProviderTest.php new file mode 100755 index 0000000..f1f821c --- /dev/null +++ b/tests/SmsSender/Tests/Provider/WebsmsProviderTest.php @@ -0,0 +1,117 @@ +getMock('\SmsSender\HttpAdapter\HttpAdapterInterface'); + $provider = new WebsmsProvider($adapter, null, null); + $provider->send('066412345678', 'foo!'); + } + + public function testSend() + { + $provider = $this->getProvider($this->getMockAdapter()); + $result = $provider->send('066412345678', 'foo', 'originator'); + + $this->assertNull($result['id']); + $this->assertEquals(ResultInterface::STATUS_FAILED, $result['status']); + $this->assertEquals('066412345678', $result['recipient']); + $this->assertEquals('foo', $result['body']); + $this->assertEquals('originator', $result['originator']); + } + + public function testSendWithMockData() + { + $data = <<getProvider($this->getMockAdapter(null, $data)); + $result = $provider->send('066412345678', 'foo'); + + $this->assertEquals('005440da3e00078f5214', $result['id']); + $this->assertEquals(ResultInterface::STATUS_SENT, $result['status']); + $this->assertEquals('066412345678', $result['recipient']); + $this->assertEquals('foo', $result['body']); + } + + /** + * @dataProvider validRecipientProvider + */ + public function testSendCleansRecipientNumber($recipient, $expectedRecipient, $internationalPrefix = null) + { + // setup the adapter + $adapter = $this->getMock('\SmsSender\HttpAdapter\HttpAdapterInterface'); + $adapter + ->expects($this->once()) + ->method('getContent') + ->with( + $this->anything(), // URL + $this->equalTo('POST'), // method + $this->anything(), // headers + $this->callback(function ($data) use ($expectedRecipient) { + $dataArray = json_decode($data, true); + + return is_array($dataArray['recipientAddressList']) + && count($dataArray['recipientAddressList']) > 0 + && $dataArray['recipientAddressList'][0] === $expectedRecipient; + }) + ); + + // setup the provider + if ($internationalPrefix === null) { + $provider = new WebsmsProvider($adapter, 'access_token'); + } else { + $provider = new WebsmsProvider($adapter, 'access_token', $internationalPrefix); + } + + // launch the test + $provider->send($recipient, 'foo'); + } + + public function validRecipientProvider() + { + return array( + array('066412345678', '4366412345678', null), + array('066412345678', '4366412345678', '+43'), + array('066412345678', '4466412345678', '+44'), + array('+4366412345678', '4366412345678', '+43'), + array('+4366412345678', '4366412345678', '+44'), + ); + } + + /** + * @requires extension curl + */ + public function testRealSend() + { + if (empty($_SERVER['WEBSMS_ACCESS_TOKEN'])) { + $this->markTestSkipped('No test credentials configured.'); + } + + $adapter = new \SmsSender\HttpAdapter\CurlHttpAdapter(); + $provider = new WebsmsProvider($adapter, $_SERVER['WEBSMS_ACCESS_TOKEN']); + $sender = new \SmsSender\SmsSender($provider); + $result = $sender->send('066412345678', 'foo'); + + $this->assertTrue(!empty($result['id'])); + $this->assertEquals(ResultInterface::STATUS_SENT, $result['status']); + $this->assertEquals('066412345678', $result['recipient']); + $this->assertEquals('foo', $result['body']); + } +}