├── .gitignore ├── src └── AliexIO │ ├── ResponseTransformer │ ├── ResponseTransformerInterface.php │ └── ResponseTransformerFactory.php │ ├── Operations │ ├── OperationInterface.php │ ├── GetProductDetail.php │ ├── GetLinks.php │ ├── AbstractOperation.php │ └── ListProducts.php │ ├── Configuration │ ├── ConfigurationInterface.php │ └── GenericConfiguration.php │ ├── Request │ ├── RequestInterface.php │ ├── RequestFactory.php │ └── Rest │ │ └── Request.php │ └── AliexIO.php ├── .travis.yml ├── tests ├── GetLinksTest.php ├── ListProductsTest.php ├── GetProductDetailTest.php ├── RequestFactoryTest.php └── AliexIOTest.php ├── phpunit.xml ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | composer.lock -------------------------------------------------------------------------------- /src/AliexIO/ResponseTransformer/ResponseTransformerInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests/ 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/AliexIO/Configuration/ConfigurationInterface.php: -------------------------------------------------------------------------------- 1 | parameter['fields'] = $fields; 15 | return $this; 16 | } 17 | public function setProductId($productId) 18 | { 19 | $this->parameter['productId'] = $productId; 20 | return $this; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clchangnet/aliexapi", 3 | "description": "AliExpress Affiliate API PHP Library", 4 | "keywords": [ 5 | "Aliexpress", 6 | "Product Advertising", 7 | "SOAP", 8 | "REST", 9 | "Affiliate Products" 10 | ], 11 | "homepage": "https://github.com/clchangnet/aliexapi", 12 | "type": "library", 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Allan Chang", 17 | "email": "allan@clchang.net" 18 | } 19 | ], 20 | "require": {}, 21 | "require-dev": { 22 | "phpunit/phpunit": "4.7.*" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "AliexApi\\": "src/AliexIO" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/AliexIO/Operations/GetLinks.php: -------------------------------------------------------------------------------- 1 | parameter['fields'] = $fields; 15 | return $this; 16 | } 17 | public function setTrackingId($trackingId) 18 | { 19 | $this->parameter['trackingId'] = $trackingId; 20 | return $this; 21 | } 22 | 23 | public function setUrls($urls) 24 | { 25 | $this->parameter['urls'] = $urls; 26 | return $this; 27 | } 28 | } -------------------------------------------------------------------------------- /src/AliexIO/Request/RequestInterface.php: -------------------------------------------------------------------------------- 1 | setApiKey('12345') 15 | ->setTrackingKey('trackkey') 16 | ->setDigitalSign('dummydigitalsign') 17 | ->setRequest(new Request()); 18 | $request = RequestFactory::createRequest($configuration); 19 | $this->assertSame($configuration, \PHPUnit_Framework_Assert::readAttribute($request, 'configuration')); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/AliexIO/Operations/AbstractOperation.php: -------------------------------------------------------------------------------- 1 | parameter; 12 | } 13 | 14 | public function __call($methodName, $parameter) 15 | { 16 | if (substr($methodName, 0, 3) == 'set') { 17 | $this->parameter[substr($methodName, 3)] = array_shift($parameter); 18 | 19 | return $this; 20 | } 21 | 22 | if (substr($methodName, 0, 3) == 'get') { 23 | $keyName = substr($methodName, 3); 24 | 25 | return isset($this->parameter[$keyName]) ? $this->parameter[$keyName] : null; 26 | } 27 | 28 | throw new \BadFunctionCallException(sprintf('The function "%s" does not exist!', $methodName)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/AliexIOTest.php: -------------------------------------------------------------------------------- 1 | setApiKey('12345') 15 | ->setTrackingKey('trackkey') 16 | ->setDigitalSign('dummydigitalsign'); 17 | return $conf; 18 | 19 | } 20 | 21 | public function testAliexIO() 22 | { 23 | $conf = new GenericConfiguration(); 24 | $this->aliconfig($conf); 25 | $aliexIO = new AliexIO($conf); 26 | 27 | $listproducts = new ListProducts(); 28 | $listproducts->setFields('productId,productTitle,productUrl,imageUrl'); 29 | $listproducts->setKeywords('card phone'); 30 | $listproducts->setCategoryId('509'); 31 | $listproducts->setHighQualityItems('true'); 32 | $formattedResponse = $aliexIO->runOperation($listproducts); 33 | 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/AliexIO/AliexIO.php: -------------------------------------------------------------------------------- 1 | configuration = $configuration; 18 | } 19 | 20 | public function runOperation(OperationInterface $operation, ConfigurationInterface $configuration = null) 21 | { 22 | $configuration = is_null($configuration) ? $this->configuration : $configuration; 23 | 24 | if (true === is_null($configuration)) { 25 | throw new \Exception('No configuration passed.'); 26 | } 27 | 28 | $requestObject = RequestFactory::createRequest($configuration); 29 | 30 | $response = $requestObject->perform($operation); 31 | 32 | return $this->applyResponseTransformer($response, $configuration); 33 | 34 | } 35 | 36 | protected function applyResponseTransformer($response, ConfigurationInterface $configuration) 37 | { 38 | if (true === is_null($configuration->getResponseTransformer())) { 39 | return $response; 40 | } 41 | 42 | $responseTransformer = ResponseTransformerFactory::createResponseTransformer($configuration); 43 | 44 | return $responseTransformer->transform($response); 45 | } 46 | } -------------------------------------------------------------------------------- /src/AliexIO/Operations/ListProducts.php: -------------------------------------------------------------------------------- 1 | parameter['fields'] = $fields; 15 | return $this; 16 | } 17 | public function setKeywords($keywords) 18 | { 19 | $this->parameter['keywords'] = $keywords; 20 | return $this; 21 | } 22 | public function setCategoryId($categoryId) 23 | { 24 | $this->parameter['categoryId'] = $categoryId; 25 | return $this; 26 | } 27 | public function setOriginalPriceFrom($originalPriceFrom) 28 | { 29 | $this->parameter['originalPriceFrom'] = $originalPriceFrom; 30 | return $this; 31 | } 32 | public function setOriginalPriceTo($originalPriceTo) 33 | { 34 | $this->parameter['originalPriceTo'] = $originalPriceTo; 35 | return $this; 36 | } 37 | public function setVolumeFrom($volumeFrom) 38 | { 39 | $this->parameter['volumeFrom'] = $volumeFrom; 40 | return $this; 41 | } 42 | public function setVolumeTo($volumeTo) 43 | { 44 | $this->parameter['volumeTo'] = $volumeTo; 45 | return $this; 46 | } 47 | public function setPageNo($pageNo) 48 | { 49 | $this->parameter['pageNo'] = $pageNo; 50 | return $this; 51 | } 52 | public function setPageSize($pageSize) 53 | { 54 | $this->parameter['pageSize'] = $pageSize; 55 | return $this; 56 | } 57 | public function setSort($sort) 58 | { 59 | $this->parameter['sort'] = $sort; 60 | return $this; 61 | } 62 | public function setStartCreditScore($startCreditScore) 63 | { 64 | $this->parameter['startCreditScore'] = $startCreditScore; 65 | return $this; 66 | } 67 | public function setEndCreditScore($endCreditScore) 68 | { 69 | $this->parameter['endCreditScore'] = $endCreditScore; 70 | return $this; 71 | } 72 | public function setHighQualityItems($highQualityItems) 73 | { 74 | $this->parameter['highQualityItems'] = $highQualityItems; 75 | return $this; 76 | } 77 | public function setLocalCurrency($localCurrency) 78 | { 79 | $this->parameter['localCurrency'] = $localCurrency; 80 | return $this; 81 | } 82 | } -------------------------------------------------------------------------------- /src/AliexIO/ResponseTransformer/ResponseTransformerFactory.php: -------------------------------------------------------------------------------- 1 | getResponseTransformer(); 21 | $factoryCallback = $configuration->getResponseTransformerFactory(); 22 | 23 | if (true === is_object($class) && $class instanceof ResponseTransformerInterface) { 24 | return self::applyCallback($factoryCallback, $class); 25 | } 26 | 27 | if (true === is_string($class) && true === array_key_exists($class, self::$responseTransformerObjects)) { 28 | return self::applyCallback($factoryCallback, self::$responseTransformerObjects[$class]); 29 | } 30 | 31 | try { 32 | $reflectionClass = new \ReflectionClass($class); 33 | } catch (\ReflectionException $e) { 34 | throw new \InvalidArgumentException(sprintf("Responsetransformerclass not found: %s", $class)); 35 | } 36 | 37 | if ($reflectionClass->implementsInterface('\\Clchang\\AliexApi\\ResponseTransformerInterface')) { 38 | $responseTransformer = new $class(); 39 | 40 | return self::$responseTransformerObjects[$class] = self::applyCallback( 41 | $factoryCallback, 42 | $responseTransformer 43 | ); 44 | } 45 | 46 | throw new \LogicException( 47 | sprintf( 48 | "Responsetransformerclass does not implements the ResponseTransformerInterface: %s", 49 | $class 50 | ) 51 | ); 52 | } 53 | 54 | protected static function applyCallback($callback, $responseTransformer) 55 | { 56 | if (false === is_null($callback) && is_callable($callback)) { 57 | $responseTransformer = call_user_func($callback, $responseTransformer); 58 | if ($responseTransformer instanceof ResponseTransformerInterface) { 59 | return $responseTransformer; 60 | } 61 | 62 | throw new \LogicException( 63 | sprintf( 64 | "Responsetransformerclass does not implements the ResponseTransformerInterface: %s", 65 | get_class($responseTransformer) 66 | ) 67 | ); 68 | } 69 | 70 | return $responseTransformer; 71 | } 72 | } -------------------------------------------------------------------------------- /src/AliexIO/Request/RequestFactory.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class RequestFactory 13 | { 14 | 15 | private static $requestObjects = array(); 16 | 17 | private function __construct() 18 | { 19 | // noop 20 | } 21 | 22 | private function __clone() 23 | { 24 | // noop 25 | } 26 | 27 | public static function createRequest(ConfigurationInterface $configuration) 28 | { 29 | $class = $configuration->getRequest(); 30 | $factoryCallback = $configuration->getRequestFactory(); 31 | 32 | if (true === is_object($class) && $class instanceof \AliexApi\Request\RequestInterface) { 33 | $class->setConfiguration($configuration); 34 | 35 | return self::applyCallback($factoryCallback, $class); 36 | } 37 | 38 | if (true === is_string($class) && true === array_key_exists($class, self::$requestObjects)) { 39 | $request = self::$requestObjects[$class]; 40 | $request->setConfiguration($configuration); 41 | 42 | return self::applyCallback($factoryCallback, $request); 43 | } 44 | 45 | try { 46 | $reflectionClass = new \ReflectionClass($class); 47 | } catch (\ReflectionException $e) { 48 | throw new \InvalidArgumentException(sprintf("Requestclass not found: %s", $class)); 49 | } 50 | 51 | if ($reflectionClass->implementsInterface('\\AliexApi\\Request\\RequestInterface')) { 52 | $request = new $class(); 53 | $request->setConfiguration($configuration); 54 | 55 | return self::$requestObjects[$class] = self::applyCallback($factoryCallback, $request); 56 | } 57 | 58 | throw new \LogicException(sprintf("Requestclass does not implements the RequestInterface: %s", $class)); 59 | } 60 | 61 | protected static function applyCallback($callback, $request) 62 | { 63 | if (false === is_null($callback) && is_callable($callback)) { 64 | $request = call_user_func($callback, $request); 65 | if ($request instanceof RequestInterface) { 66 | return $request; 67 | } 68 | 69 | throw new \LogicException( 70 | sprintf( 71 | "Requestclass does not implements the RequestInterface: %s", 72 | get_class($request) 73 | ) 74 | ); 75 | } 76 | 77 | return $request; 78 | } 79 | } -------------------------------------------------------------------------------- /src/AliexIO/Configuration/GenericConfiguration.php: -------------------------------------------------------------------------------- 1 | apiKey; 25 | } 26 | 27 | public function setApiKey($apiKey) 28 | { 29 | $this->apiKey = $apiKey; 30 | 31 | return $this; 32 | } 33 | 34 | public function getTrackingKey() 35 | { 36 | return $this->trackingKey; 37 | } 38 | 39 | public function setTrackingKey($trackingKey) 40 | { 41 | $this->trackingKey = $trackingKey; 42 | 43 | return $this; 44 | } 45 | 46 | public function getDigitalSign() 47 | { 48 | return $this->digitalSign; 49 | } 50 | 51 | public function setDigitalSign($digitalSign) 52 | { 53 | $this->digitalSign = $digitalSign; 54 | 55 | return $this; 56 | } 57 | 58 | public function getRequest() 59 | { 60 | return $this->request; 61 | } 62 | 63 | public function setRequest($request) 64 | { 65 | $this->request = $request; 66 | 67 | return $this; 68 | } 69 | 70 | public function getRequestFactory() 71 | { 72 | return $this->requestFactory; 73 | } 74 | 75 | public function setRequestFactory($callback) 76 | { 77 | if (!is_callable($callback)) { 78 | throw new \InvalidArgumentException("Given argument is not callable"); 79 | } 80 | 81 | $this->requestFactory = $callback; 82 | 83 | return $this; 84 | } 85 | 86 | public function getResponseTransformer() 87 | { 88 | return $this->responseTransformer; 89 | } 90 | 91 | public function setResponseTransformer($responseTransformer) 92 | { 93 | $this->responseTransformer = $responseTransformer; 94 | 95 | return $this; 96 | } 97 | 98 | public function getResponseTransformerFactory() 99 | { 100 | return $this->responseTransformerFactory; 101 | } 102 | 103 | public function setResponseTransformerFactory($callback) 104 | { 105 | if (!is_callable($callback)) { 106 | throw new \InvalidArgumentException("Given argument is not callable"); 107 | } 108 | 109 | $this->responseTransformerFactory = $callback; 110 | 111 | return $this; 112 | } 113 | 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/AliexIO/Request/Rest/Request.php: -------------------------------------------------------------------------------- 1 | options = array( 26 | self::USERAGENT => "AliexIO [" . AliexIO::VERSION . "]", 27 | self::CONNECTION_TIMEOUT => 10, 28 | self::TIMEOUT => 10, 29 | self::FOLLOW_LOCATION => 1 30 | ); 31 | $this->setOptions($options); 32 | } 33 | 34 | public function setOptions(array $options = array()) 35 | { 36 | foreach ($options as $currentOption => $currentOptionValue) { 37 | $this->options[$currentOption] = $currentOptionValue; 38 | } 39 | $this->options[CURLOPT_RETURNTRANSFER] = 1; // force the return transfer 40 | } 41 | 42 | public function getOptions() 43 | { 44 | return $this->options; 45 | } 46 | 47 | public function setConfiguration(ConfigurationInterface $configuration) 48 | { 49 | $this->configuration = $configuration; 50 | } 51 | 52 | public function perform(OperationInterface $operation) 53 | { 54 | $ch = curl_init(); 55 | 56 | if (false === $ch) { 57 | throw new \RuntimeException("Cannot initialize curl resource"); 58 | } 59 | 60 | $preparedRequestParams = $this->prepareRequestParams($operation); 61 | 62 | $queryString = $this->buildQueryString($preparedRequestParams); 63 | 64 | $options = $this->options; 65 | 66 | $options[CURLOPT_URL] = sprintf($this->requestScheme, $queryString); 67 | 68 | foreach ($options as $currentOption => $currentOptionValue) { 69 | if (false === curl_setopt($ch, $currentOption, $currentOptionValue)) { 70 | throw new \RuntimeException( 71 | sprintf( 72 | "An error occurred while setting %s with value %s", 73 | $currentOption, 74 | $currentOptionValue 75 | ) 76 | ); 77 | } 78 | } 79 | 80 | $curlError = false; 81 | $errorNumber = null; 82 | $errorMessage = null; 83 | 84 | $result = curl_exec($ch); 85 | 86 | if (false === $result) { 87 | $curlError = true; 88 | $errorNumber = curl_errno($ch); 89 | $errorMessage = curl_error($ch); 90 | } 91 | 92 | curl_close($ch); 93 | 94 | if ($curlError) { 95 | throw new \RuntimeException( 96 | sprintf( 97 | "An error occurred while sending request. Error number: %d; Error message: %s", 98 | $errorNumber, 99 | $errorMessage 100 | ) 101 | ); 102 | } 103 | 104 | return $result; 105 | } 106 | 107 | protected function prepareRequestParams(OperationInterface $operation) 108 | { 109 | $baseRequestParams = array( 110 | 'ApiKey' => $this->configuration->getApiKey(), 111 | 'Operation' => $operation->getName(), 112 | ); 113 | 114 | $operationParams = $operation->getOperationParameter(); 115 | 116 | foreach ($operationParams as $key => $value) { 117 | if (true === is_array($value)) { 118 | $operationParams[$key] = implode(',', $value); 119 | } 120 | } 121 | 122 | $fullParameterList = array_merge($baseRequestParams, $operationParams); 123 | // ksort($fullParameterList); 124 | 125 | return $fullParameterList; 126 | } 127 | 128 | protected function buildQueryString(array $params) 129 | { 130 | $parameterList = array(); 131 | 132 | $baseQueryString = sprintf('api.%s/%s?', $params['Operation'], $params['ApiKey']); 133 | $params = array_slice($params,2); 134 | 135 | foreach ($params as $key => $value) { 136 | $parameterList[] = sprintf('%s=%s', $key, rawurlencode($value)); 137 | } 138 | 139 | return $baseQueryString . implode("&", $parameterList); 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # THIS WILL NOT WORK WITH THE UPDATED ALIEXPRESS API, TAOBAO OPEN PLATFORM API 2 | 3 | 4 | # aliexapi 5 | 6 | [![Build Status](https://travis-ci.org/clchangnet/aliexapi.svg?branch=master)](https://travis-ci.org/clchangnet/aliexapi) [![Latest Stable Version](https://poser.pugx.org/clchangnet/aliexapi/v/stable)](https://packagist.org/packages/clchangnet/aliexapi) [![Total Downloads](https://poser.pugx.org/clchangnet/aliexapi/downloads)](https://packagist.org/packages/clchangnet/aliexapi) [![License](https://poser.pugx.org/clchangnet/aliexapi/license)](https://packagist.org/packages/clchangnet/aliexapi) 7 | 8 | AliexApi is a PHP library for AliExpress Affiliate API program. You can use it to fetch product data. It interfaces with Aliexpress API functions such as listPromotionProduct, getPromotionProductDetail and getPromotionLinks. For more info on the API, visit [http://portals.aliexpress.com/help/help_center_API.html](http://portals.aliexpress.com/help/help_center_API.html). To see a working demo site, goto [clothes, warmers and headwear](https://apparel.iopenshop.net/). 9 | 10 | This Library based on Jan Eichhorn's [Amazon Product Advertising API](https://github.com/Exeu/apai-io). 11 | 12 | If you like this package, feel free to [buy me a coffee](https://www.paypal.me/aliexapi/5) ☕️ 13 | 14 | ## AliExpress Affiliate Program 15 | 16 | To signup and join the program, goto http://portals.aliexpress.com/, you need to apply for API Key to get access. 17 | 18 | ## Installation 19 | 20 | ### Composer 21 | 22 | Add the package 'clchangnet/aliexapi' to composer.json file: 23 | 24 | ```js 25 | { 26 | "require": { 27 | "clchangnet/aliexapi": "~1.0" 28 | } 29 | } 30 | ``` 31 | 32 | Update composer of the new package and download. 33 | Once done, you should see a folder 'clchangnet' under 'vendor' folder. 34 | 35 | ```bash 36 | $ composer update 37 | $ composer install 38 | ``` 39 | 40 | This will update the autoloader file and the library would be found once you include it in your code. 41 | 42 | ##Basic Usage: 43 | 44 | Here is an example how to use Aliexpress API listPromotionProduct to search for products using keywords. 45 | 46 | ###Search Products 47 | 48 | _Note:_ 49 | To search by category. uncomment 'categoryId' and comment 'keywords' in searchItems and listPromotionProduct 50 | 51 | ```php 52 | setApiKey('ALI_API_KEY') 69 | ->setTrackingKey('ALI_TRACKING_ID') 70 | ->setDigitalSign('ALI_DIGITAL_SIGNATURE'); 71 | return $conf; 72 | } 73 | 74 | public function index() 75 | { 76 | $this->searchItems(); 77 | } 78 | 79 | public function searchItems() 80 | { 81 | $lppfields = [ 82 | // 'categoryId' => '1501', 83 | 'keywords' => 'baby shoes', 84 | ]; 85 | $array = $this->listPromotionProduct($lppfields); 86 | dd($array); 87 | } 88 | 89 | public function listPromotionProduct($lppfields) 90 | { 91 | $conf = new GenericConfiguration(); 92 | $this->aliconfig($conf); 93 | $aliexIO = new AliexIO($conf); 94 | 95 | $listproducts = new ListProducts(); 96 | $listproducts->setFields('productId,productTitle,productUrl,imageUrl'); 97 | $listproducts->setKeywords($lppfields['keywords']); 98 | // $listproducts->setCategoryId($lppfields['categoryId']); 99 | $listproducts->setHighQualityItems('true'); 100 | 101 | $formattedResponse = $aliexIO->runOperation($listproducts); 102 | $array = json_decode($formattedResponse, true); 103 | 104 | $array = array_merge($array, $lppfields); 105 | 106 | return $array; 107 | 108 | } 109 | } 110 | 111 | ``` 112 | 113 | ###Get Affiliate Links 114 | 115 | ```php 116 | public function getPromotionLinks() 117 | { 118 | $conf = new GenericConfiguration(); 119 | $this->aliconfig($conf); 120 | $aliexIO = new AliexIO($conf); 121 | 122 | $listproducts = new GetLinks(); 123 | $listproducts->setFields('url,promotionUrl'); 124 | $listproducts->setTrackingId('ALI_TRACKING_ID'); 125 | $listproducts->setUrls('http://url1, http://url2'); 126 | 127 | $formattedResponse = $aliexIO->runOperation($listproducts); 128 | $array = json_decode($formattedResponse, true); 129 | return $array; 130 | } 131 | ``` 132 | 133 | Example Workflow: 134 | Use ListProducts to search using keywords and set what fields to return. 135 | Use GetLinksTo convert product urls to your affiliate link. 136 | 137 | ##Webservice Documentation: 138 | 139 | To find out about what fields can be return through API request, goto http://portals.aliexpress.com/help/help_center_API.html 140 | --------------------------------------------------------------------------------