diff --git a/README.md b/README.md
index 715cd27..7325bdf 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
premium-api
===========
-Client API for Sales.lv **[Premium](http://www.sales.lv/lv/risinajumi/premium/)** service. In its essence **Premium** is a platform for
+Client API for Sales.lv **[Premium](https://sales.lv/sms/sms-premium/)** service. In its essence **Premium** is a platform for
implementing services based on mobile-originated (incoming from users) SMS message processing. In practice there are a number of applications
built upon this platform, for example, user message processing, SMS micropayment handling, lotteries, etc. (Lotteries are a special case
as there is a lot of lottery-specific functionality implemented in Premium that goes above and beyond SMS processing).
@@ -14,7 +14,7 @@ as well as examples of using our libraries
A quick start guide
------------
-- Sign up for the [Premium service with Sales.lv](http://www.sales.lv/lv/risinajumi/premium/). Once you have done that, you will be provided with an API key and a campaign code to use for API requests.
+- Sign up for the [Premium service with Sales.lv](https://sales.lv/sms/sms-premium/). Once you have done that, you will be provided with an API key and a campaign code to use for API requests.
- Take a look at the [API documentation](https://github.com/Sales-LV/premium-api/wiki) and the client libraries.
PHP client library
@@ -22,14 +22,24 @@ PHP client library
PHP client library is located in `lib/php/premium-api.php`. An usage example is provided in `lib/php/example.php`.
Requirements:
-* [PHP 5.2 or newer](http://www.php.net/)
+* [PHP 5.5 or newer](http://www.php.net/)
* One of these:
* [pecl_http](http://pecl.php.net/package/pecl_http) extension is recommended but not mandatory.
* enabled [cURL library](http://www.php.net/manual/en/book.curl.php).
- * [allow_url_fopen](http://php.net/manual/en/filesystem.configuration.php) set to true.
+ * [allow_url_fopen](http://php.net/manual/en/filesystem.configuration.php) set to true (attachment file upload is not currently supported for this method.)
Library usage is [described in the wiki](https://github.com/Sales-LV/premium-api/wiki/PHP-API-library).
+Changelog
+------------
+1.1.0:
+- compatibility moved up to 5.5;
+- some error messages indicate data unavailability due to GDPR limitations;
+- files can be attached to submitted messages for upload and storage in Premium (when required by the campaign)
+
+1.0.*:
+- initial releases
+
Feedback, support & questions
------------
Please write to support@sales.lv with any feedback, questions or suggestions that might arise.
\ No newline at end of file
diff --git a/lib/php/example.php b/lib/php/example.php
index c825a95..80a9d7e 100644
--- a/lib/php/example.php
+++ b/lib/php/example.php
@@ -41,11 +41,11 @@ function debug_output(PremiumAPI $APIObject)
// Messages
echo '
Message list retrieval
';
- $Messages = $PremiumAPI -> Messages_List(array(
+ $Messages = $PremiumAPI -> Messages_List([
'Time' => date('c', strtotime('2010-02-07'))
- ), array(
+ ], [
'Time' => date('c', strtotime('2010-02-09'))
- ));
+ ]);
debug_output($PremiumAPI);
error_output($PremiumAPI);
results_output($Messages);
@@ -57,14 +57,17 @@ function debug_output(PremiumAPI $APIObject)
results_output($Message);
echo 'Create a new message
';
- $Message = $PremiumAPI -> Messages_Create(array(
+ $Message = $PremiumAPI -> Messages_Create([
'Phone' => 21234567,
'FirstName' => 'George',
'LastName' => 'Brown',
'ReceiptUnique' => '123/456',
'IP' => $_SERVER['REMOTE_ADDR']
- ));
+ ],
+ [ // Attachments
+ ['tmp_name' => getcwd().'/example.php', 'type' => 'text/php', 'name' => 'example.php'],
+ ['tmp_name' => getcwd().'/premium-api.php', 'type' => 'text/php', 'name' => 'premium-api.php'],
+ ]);
debug_output($PremiumAPI);
error_output($PremiumAPI);
results_output($Message);
-?>
\ No newline at end of file
diff --git a/lib/php/premium-api.php b/lib/php/premium-api.php
index fddfce6..c77b13f 100644
--- a/lib/php/premium-api.php
+++ b/lib/php/premium-api.php
@@ -2,12 +2,14 @@
/**
* Utility class for Premium API connection
*
- * @version 1.0.4
+ * @version 1.1.0
*/
class PremiumAPI
{
- private static $Version = '1.0.4';
+ private static $Version = '1.1.0';
private static $UserAgent = 'SalesLV/Premium-API';
+ private static $UAString = '';
+
private static $VerifySSL = false;
// Error constants
@@ -48,6 +50,23 @@ class PremiumAPI
const ERROR_INVALID_API_VERSION = 16;
// Invalid data format requested. Same as above.
const ERROR_INVALID_DATA_FORMAT = 17;
+ // 1.1.0: Attachment support
+ const ERROR_ATTACHMENTS_NOT_ALLOWED = 18;
+ // File type of the attachment is not permitted (e.g. only images are allowed and you're trying to upload a zip file.)
+ const ERROR_ATTACHMENT_TYPE_NOT_PERMITTED = 19;
+ // File upload failed, you chould notify the user and rectify the situation
+ const ERROR_ATTACHMENT_UPLOAD_FAILED = 20;
+ // Indicates that message data has been processed successfully but there was a problem with handling the attached file(s).
+ // User should be notified to recitfy the sitation or inform them that their file was not saved.
+ const ERROR_MESSAGE_SUCCESSFUL_BUT_ATTACHMENT_FAILED = 21;
+ // The list of attachments passed to some method doesn't conform to the specification
+ const ERROR_MALFORMED_ATTACHMENT_ARRAY = 22;
+ // The file that should be added as an attachment was not accessible
+ const ERROR_ATTACHMENT_FILE_NOT_READABLE = 23;
+ // PHP version incompatible with this library
+ const ERROR_PHP_VERSION_INCOMPATIBLE = 24;
+ // Attachments upload not supported with the current configuration
+ const ERROR_ATTACHMENTS_NOT_SUPPORTED_WITH_THIS_METHOD = 25;
/**
* @var string API endpoint URL
@@ -75,13 +94,13 @@ class PremiumAPI
*/
private $Error = '';
- public $Debug = array(
- 'LastHTTPRequest' => array(
+ public $Debug = [
+ 'LastHTTPRequest' => [
'URL' => '',
- 'Request' => array(),
- 'Response' => array()
- )
- );
+ 'Request' => [],
+ 'Response' => []
+ ]
+ ];
// !Public utility methods
@@ -92,6 +111,20 @@ class PremiumAPI
*/
public function __construct($Key, $CampaignCode)
{
+ self::$UAString = self::$UserAgent.'/'.self::$Version;
+ if (extension_loaded('http'))
+ {
+ self::$UAString .= '-http';
+ }
+ elseif (extension_loaded('curl'))
+ {
+ self::$UAString .= '-curl';
+ }
+ elseif (ini_get('allow_url_fopen'))
+ {
+ self::$UAString .= '-stream';
+ }
+
$this -> APIKey = $Key;
$this -> CampaignCode = $CampaignCode;
@@ -162,11 +195,11 @@ public function Messages_List(array $Parameters, array $Parameters2 = null, $Off
{
$Data = $this -> HTTPRequest(
$this -> APIURL.'Messages:List',
- array(
+ [
'Filter1' => json_encode($Parameters),
'Filter2' => $Parameters2 ? json_encode($Parameters2) : false,
'Offset' => (int)$Offset
- )
+ ]
);
return $this -> ParseResponse($Data);
@@ -176,19 +209,42 @@ public function Messages_List(array $Parameters, array $Parameters2 = null, $Off
* Method for submitting a new message
*
* @param array Message parameters
+ * @param array Optional file attachments (array of file paths to upload). Should contain an array for each file with the following parameters
+ * (same as in the $_FILES array):
+ * - string name: Original file name
+ * - string type: File type
+ * - string tmp_name: Current path to file from where it can be read.
*
* @return array Operation result
*/
- public function Messages_Create(array $Parameters)
+ public function Messages_Create(array $Parameters, array $Attachments = null)
{
if (empty($Parameters['IP']))
{
$Parameters['IP'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
}
+ if ($Attachments)
+ {
+ foreach ($Attachments as $Attachment)
+ {
+ if (!isset($Attachment['tmp_name']) || !isset($Attachment['type']) || !isset($Attachment['name']))
+ {
+ return $this -> SetError(self::ERROR_MALFORMED_ATTACHMENT_ARRAY, 'Attachment list does not conform to specification');
+ }
+
+ if (!is_readable($Attachment['tmp_name']))
+ {
+ return $this -> SetError(self::ERROR_ATTACHMENT_FILE_NOT_READABLE, 'Attachment file "'.$Attachment['tmp_name'].'" was not readable');
+ }
+ }
+ }
+
$Result = $this -> HTTPRequest(
$this -> APIURL.'Messages:Create',
- $Parameters
+ $Parameters,
+ null, // Additional headers
+ $Attachments // Attachment files
);
return $this -> ParseResponse($Result);
@@ -259,28 +315,32 @@ private function SetError($ErrorCode, $ErrorMessage)
* 'Content' => string Response body
* )
*/
- private function HTTPRequest($URL, array $POSTData = null, array $Headers = null)
+ private function HTTPRequest($URL, array $POSTData = null, array $Headers = null, array $Files = null)
{
$this -> Debug['LastHTTPRequest']['URL'] = $URL;
$this -> Debug['LastHTTPRequest']['Method'] = $POSTData ? 'POST' : 'GET';
$this -> Debug['LastHTTPRequest']['Request'] = $POSTData;
$this -> Debug['LastHTTPRequest']['Response'] = '';
- $Result = array();
+ $Result = [];
try
{
if (extension_loaded('http'))
{
- $Result = self::HTTPRequest_http($URL, $POSTData, $Headers);
+ $Result = self::HTTPRequest_http($URL, $POSTData, $Headers, $Files);
}
elseif (extension_loaded('curl'))
{
- $Result = self::HTTPRequest_curl($URL, $POSTData, $Headers);
+ $Result = self::HTTPRequest_curl($URL, $POSTData, $Headers, $Files);
}
elseif (ini_get('allow_url_fopen'))
{
- $Result = self::HTTPRequest_fopen($URL, $POSTData, $Headers);
+ if ($Files)
+ {
+ return $this -> SetError(self::ERROR_ATTACHMENTS_NOT_SUPPORTED_WITH_THIS_METHOD, 'Attachment upload not supported for this HTTP connection method (stream context,) please install curl or pecl_http');
+ }
+ $Result = self::HTTPRequest_fopen($URL, $POSTData, $Headers, $Files);
}
else
{
@@ -302,7 +362,7 @@ private function HTTPRequest($URL, array $POSTData = null, array $Headers = null
/**
* Utility method for making HTTP requests with the pecl_http extension, see HTTPRequest for more information
*/
- private static function HTTPRequest_http($URL, array $POSTData = null, array $Headers = null)
+ private static function HTTPRequest_http($URL, array $POSTData = null, array $Headers = null, array $Files = null)
{
$Method = $POSTData ? HttpRequest::METH_POST : HttpRequest::METH_GET;
@@ -313,78 +373,99 @@ private static function HTTPRequest_http($URL, array $POSTData = null, array $He
}
$Request -> setPostFields($POSTData);
+ if ($Files)
+ {
+ foreach ($Files as $File)
+ {
+ $Request -> addPostFile($File['name'], $File['tmp_name'], $File['type']);
+ }
+ }
+
$Request -> send();
- return array(
+ return [
'Headers' => array_merge(
- array(
+ [
'Response Code' => $Request -> getResponseCode(),
'Response Status' => $Request -> getResponseStatus()
- ),
+ ],
$Request -> getResponseHeader()
),
'Body' => $Request -> getResponseBody()
- );
+ ];
}
/**
* Utility method for making HTTP requests with CURL. See PremiumAPI::HTTPRequest for more information
*/
- private static function HTTPRequest_curl($URL, array $POSTData = null, array $Headers = null)
+ private static function HTTPRequest_curl($URL, array $POSTData = null, array $Headers = null, array $Files = null)
{
- // Preparing request content
- $POSTBody = $POSTData ? self::PrepareBody($POSTData) : '';
+ if ($Files)
+ {
+ if (!$POSTData)
+ {
+ $POSTData = [];
+ }
+
+ $Index = 0;
+ foreach ($Files as $File)
+ {
+ $POSTData['Attachment['.$Index.']'] = curl_file_create($File['tmp_name'], $File['type'], $File['name']);
+ $Index++;
+ }
+ }
// Preparing request headers
- $Headers = self::PrepareHeaders($Headers, $URL, strlen($POSTBody));
+ $Headers = ['Expect' => ''];
+ $Headers = self::PrepareHeaders($Headers, $URL);
- // Making the request
- $cURLRequest = curl_init();
- curl_setopt_array($cURLRequest, array(
+ $cURLParams = [
CURLOPT_URL => $URL,
CURLOPT_HEADER => 1,
CURL_HTTP_VERSION_1_0 => true,
- CURLOPT_POST => $POSTBody ? 1 : 0,
+ CURLOPT_POST => $POSTData ? 1 : 0,
CURLOPT_CONNECTTIMEOUT => 60,
CURLOPT_TIMEOUT => 120,
CURLOPT_MAXREDIRS => 5,
- CURLOPT_USERAGENT => self::$UserAgent.'/'.self::$Version,
- CURLOPT_POSTFIELDS => $POSTBody,
+ CURLOPT_FAILONERROR => 1,
+ CURLOPT_USERAGENT => self::$UAString,
+ CURLOPT_SAFE_UPLOAD => true,
+ CURLOPT_POSTFIELDS => $POSTData,
CURLOPT_ENCODING => 'gzip',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_HTTPHEADER => $Headers,
CURLOPT_SSL_VERIFYPEER => self::$VerifySSL
- ));
+ ];
+
+ // Making the request
+ $cURLRequest = curl_init();
+ curl_setopt_array($cURLRequest, $cURLParams);
$ResponseBody = curl_exec($cURLRequest);
curl_close($cURLRequest);
- $ResponseBody = str_replace(array("\r\n", "\n\r", "\r"), array("\n", "\n", "\n"), $ResponseBody);
+ $ResponseBody = str_replace(["\r\n", "\n\r", "\r"], ["\n", "\n", "\n"], $ResponseBody);
$ResponseParts = explode("\n\n", $ResponseBody);
- $ResponseHeaders = array();
+ $ResponseHeaders = [];
if (count($ResponseParts) > 1)
{
$ResponseHeaders = self::ParseHeadersFromString($ResponseParts[0]);
}
$ResponseBody = isset($ResponseParts[1]) ? $ResponseParts[1] : $ResponseBody;
- //if (isset($ResponseHeaders['Content-Encoding']) && $ResponseHeaders['Content-Encoding'] == 'gzip')
- //{
- //$ResponseBody = gzinflate($ResponseBody);
- //}
- return array(
+ return [
'Headers' => $ResponseHeaders,
'Body' => $ResponseBody
- );
+ ];
}
/**
* Utility method for making the HTTP request with file_get_contents. See PremiumAPI::HTTPRequest for more information
*/
- private static function HTTPRequest_fopen($URL, array $POSTData = null, array $Headers = null)
+ private static function HTTPRequest_fopen($URL, array $POSTData = null, array $Headers = null, array $Files = null)
{
- // Preparing reqiest body
+ // Preparing request body
$POSTBody = $POSTData ? self::PrepareBody($POSTData) : '';
// Preparing headers
@@ -392,24 +473,24 @@ private static function HTTPRequest_fopen($URL, array $POSTData = null, array $H
$Headers = implode("\r\n", $Headers)."\r\n";
// Making the request
- $Context = stream_context_create(array(
- 'http' => array(
+ $Context = stream_context_create([
+ 'http' => [
'method' => $POSTBody ? 'POST' : 'GET',
'header' => $Headers,
'content' => $POSTBody,
'protocol_version' => 1.0
- )
- ));
+ ]
+ ]);
$Content = file_get_contents($URL, false, $Context);
$ResponseHeaders = $http_response_header;
$ResponseHeaders = self::ParseHeadersFromArray($ResponseHeaders);
- return array(
+ return [
'Headers' => $ResponseHeaders,
'Body' => $Content
- );
+ ];
}
/**
@@ -417,22 +498,25 @@ private static function HTTPRequest_fopen($URL, array $POSTData = null, array $H
*
* @param array Headers to send in addition to the default set (keys are names, values are content)
* @param string URL that will be used for the request (for the "Host" header)
- * @param int Content length for the Content-Length header
+ * @param int Optional content length for the Content-Length header
*
* return array Headers in a numeric array. Each item in the array is a separate header string containing both name and content
*/
- private static function PrepareHeaders(array $Headers = null, $URL, $ContentLength)
+ private static function PrepareHeaders(array $Headers = null, $URL, $ContentLength = null)
{
$URLInfo = parse_url($URL);
$Host = $URLInfo['host'];
- $DefaultHeaders = array(
+ $DefaultHeaders = [
'Host' => $Host,
'Connection' => 'close',
- 'Content-Type' => 'application/x-www-form-urlencoded',
- 'Content-Length' => $ContentLength,
- 'User-Agent' => self::$UserAgent.'/'.self::$Version
- );
+ 'User-Agent' => self::$UAString
+ ];
+
+ if (!is_null($ContentLength))
+ {
+ $DefaultHeaders['Content-Length'] = $ContentLength;
+ }
if ($Headers)
{
@@ -443,7 +527,7 @@ private static function PrepareHeaders(array $Headers = null, $URL, $ContentLeng
$Headers = $DefaultHeaders;
}
- $Result = array();
+ $Result = [];
foreach ($Headers as $Name => $Content)
{
$Result[] = $Name.': '.$Content;
@@ -460,7 +544,7 @@ private static function PrepareHeaders(array $Headers = null, $URL, $ContentLeng
*/
private static function PrepareBody(array $Data)
{
- $POSTBody = array();
+ $POSTBody = [];
foreach ($Data as $Key => $Value)
{
$POSTBody[] = $Key.'='.urlencode($Value);
@@ -504,7 +588,7 @@ private static function ParseHeadersFromString($HeaderString)
*/
private static function ParseHeadersFromArray(array $Headers)
{
- $Result = array();
+ $Result = [];
$CurrentHeader = 0;