Last Updated: August 08, 2017
·
26.33K
· croustibat

PRESTASHOP background/cron CSV products import

Here's useful code I use on one of my project with a multi-shop setup PRESTASHOP (v1.5.6) to automatically import product for each shops. First i generate the CSV file with the product data i want to insert or update, then the script log in like you would do on the prestashop admin area and POST the data on the AdminImport controller.

Here is the background/cron script and below the curl wrapper class (You can replace the php curl wrapper of course)


require_once ('class.PSRequest.php'); //see class source code below

$shopID = "myfirstshop"; // ID or unqiue name of the target shop
$products = ...; // your set of product object or array

// CSV first line for products
$csv = "id;Active (0/1);Name*;Categories (x,y,z,...);Price tax excluded;Tax rules id;Wholesale price;On sale (0/1);Discount amount;Discount percent;Discount from (yyy-mm-dd);Discount to (yyy-mm-dd);Reference #;Supplier reference #;Supplier;Manufacturer;EAN13;UPC;Ecotax;Weight;Quantity;Short description;Description;Tags (x,y,z,...);Meta-title;Meta-keywords;Meta-description;URL rewritten;Text when in-stock;Text if back-order allowed;Available for order (0 = No, 1 = Yes);Product creation date;Show price (0 = No, 1 = Yes);Image URLs (x,y,z,...);Delete existing images (0 = No, 1 = Yes);Feature (Name:Value:Position);Available online only (0 = No, 1 = Yes);Condition (new,used,refurbished);ID / Name of shop".PHP_EOL;

foreach ($products as $prod) {
        // fill in the csv string with your datas
       $csv .= $prod->id.";1;".html_entity_decode($prod->name)......$shopID.PHP_EOL;
}

$now=time();
$csvname = $now."-PRODUCTS-".$shopID.".csv";
$file = YOUR_PATH.$csvname;
file_put_contents($file, $csv);

echo "Write file : ".$file.PHP_EOL;

echo "Login on Prestashop Admin area...".PHP_EOL;   
$adminUrl = "http://YOUR_PS_ADMIN/adminXXXX/"; // change that with your admin url of course
$request = new PSRequest();
$request->setCookiFileLocation(__DIR__.'/PScookie.txt');

$request->setPost(array("email" => "YOUR_ADMIN_EMAIL","passwd" => "YOUR_ADMIN_PASS", "submitLogin" => "Connexion")); // you must be a super admin
$request->call($adminUrl."index.php?controller=AdminLogin");

echo "Get token...".PHP_EOL;

$request->call($adminUrl."index.php?controller=AdminImport");
list(,$response) = explode("\r\n\r\n", $request->_webpage, 2);
preg_match("/token=([a-z0-9]+)/", $response, $matches);
$token = $matches[1];

echo "Token : ".$token.PHP_EOL;

// Send POST datas just like the admin form would do it, those datas depends on what you want to do : check the import admin page.
$request->setPost(array(
    "controller"               => "AdminImport",
    "token"                    => $token,
    "skip"                     => 1,
    "csv"                      => $csvname,
    "convert"                  => '',
    "regenerate"               => '',
    "entity"                   => 1, //1 is for products import
    "iso_lang"                 => "fr",
    "truncate"                 => 0,
    "forceIDs"                 => 1,
    "match_ref"                => 1,
    "separator"                => ";",
    "multiple_value_separator" => ",",
    "import"                   => 1,
    "type_value" => array( 0 => 'id', 1 => 'active', 2 => 'name', 3 => 'category', 4 => 'price_tex', 5 => 'id_tax_rules_group', 6 => 'wholesale_price', 7 => 'on_sale', 8 => 'reduction_price', 9 => 'reduction_percent', 10 => 'reduction_from', 11 => 'reduction_to', 12 => 'reference', 13 => 'supplier_reference', 14 => 'supplier', 15 => 'manufacturer', 16 => 'ean13', 17 => 'upc', 18 => 'ecotax', 19 => 'weight', 20 => 'quantity', 21 => 'description_short', 22 => 'description', 23 => 'tags', 24 => 'meta_title', 25 => 'meta_keywords', 26 => 'meta_description', 27 => 'link_rewrite', 28 => 'available_now', 29 => 'available_later', 30 => 'available_for_order', 31 => 'date_add', 32 => 'show_price', 33 => 'image', 34 => 'delete_existing_images', 35 => 'features', 36 => 'online_only', 37 => 'condition', 38 => 'shop')
    )
);

echo "call AdminImport and POST datas...".PHP_EOL;

$request->call($adminUrl."index.php?controller=AdminImport&token=".$token);

echo "-- END --".PHP_EOL;

$request = null;

Here's the wrapper curl class


class PSRequest {

    protected $_useragent          = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
    protected $_cookieFileLocation = './cookie.txt';
    protected $_referer            = "http://www.google.com";

    protected $_url;
    protected $_followlocation;
    protected $_timeout;
    protected $_maxRedirects;
    protected $_post;
    protected $_postFields;

    protected $_session;
    protected $_includeHeader;
    protected $_noBody;
    protected $_status;
    protected $_binaryTransfer;

    public $_webpage;
    public $authentication = 0;
    public $auth_name      = '';
    public $auth_pass      = '';

    protected $ch; // curl handler

    public function __construct($url = '', $followlocation = true, $timeOut = 30, $maxRedirecs = 4, $binaryTransfer = false, $includeHeader = true, $noBody = false)
    {
        $this->_url                = $url;
        $this->_followlocation     = $followlocation;
        $this->_timeout            = $timeOut;
        $this->_maxRedirects       = $maxRedirecs;
        $this->_noBody             = $noBody;
        $this->_includeHeader      = $includeHeader;
        $this->_binaryTransfer     = $binaryTransfer;

        $this->_cookieFileLocation = dirname(__FILE__).'/cookie.txt';

        $this->ch = curl_init();
    }

    public function __destruct() {
        curl_close($this->ch);
    }

    public function useAuth($use){
        $this->authentication = 0;
        if($use == true) $this->authentication = 1;
    }

    public function setName($name){
        $this->auth_name = $name;
    }

    public function setPass($pass){
        $this->auth_pass = $pass;
    }

    public function setReferer($referer){
        $this->_referer = $referer;
    }

    public function setCookiFileLocation($path)
    {
        $this->_cookieFileLocation = $path;
    }

    public function setPost($postFields)
    {
        $this->_post = true;

        if (is_array($postFields)) {
            $fields_string = http_build_query($postFields);
        }
        else {
            $fields_string = $postFields;
        }

        $this->_postFields = $fields_string;
    }

    public function setUserAgent($userAgent)
    {
        $this->_useragent = $userAgent;
    }

    public function call($url = null)
    {
        if ($url) {
            $this->_url = $url;
        }

        if (!$url) {
            throw new Exception('You should set an URL to call.');
        }

        curl_setopt($this->ch,CURLOPT_URL,$this->_url);
        curl_setopt($this->ch,CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
        curl_setopt($this->ch,CURLOPT_TIMEOUT,$this->_timeout);
        curl_setopt($this->ch,CURLOPT_MAXREDIRS,$this->_maxRedirects);
        curl_setopt($this->ch,CURLOPT_RETURNTRANSFER,true);
        curl_setopt($this->ch,CURLOPT_FOLLOWLOCATION,$this->_followlocation);
        curl_setopt($this->ch,CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($this->ch,CURLOPT_COOKIESESSION, true );
        curl_setopt($this->ch,CURLOPT_COOKIEJAR,$this->_cookieFileLocation);
        curl_setopt($this->ch,CURLOPT_COOKIEFILE,$this->_cookieFileLocation);

        if ($this->authentication == 1) {
            curl_setopt($this->ch, CURLOPT_USERPWD, $this->auth_name.':'.$this->auth_pass);
        }

        if ($this->_post) {
            curl_setopt($this->ch,CURLOPT_POST,true);
            curl_setopt($this->ch,CURLOPT_POSTFIELDS,$this->_postFields);

        }

        if ($this->_includeHeader) {
            curl_setopt($this->ch,CURLOPT_HEADER,true);
        }

        if ($this->_noBody) {
            curl_setopt($this->ch,CURLOPT_NOBODY,true);
        }

        curl_setopt($this->ch,CURLOPT_USERAGENT,$this->_useragent);
        curl_setopt($this->ch,CURLOPT_REFERER,$this->_referer);

        $this->_webpage = curl_exec($this->ch);
        $this->_status = curl_getinfo($this->ch,CURLINFO_HTTP_CODE);

        return $this->_webpage;
    }

    public function getHttpStatus()
    {
        return $this->_status;
    }

    public function __tostring(){
        return $this->_webpage;
    }

}

and that's it. Just setup your cron like this for example :

@daily /usr/bin/php /path/to/my_script.php > /dev/null 2>&1

You can add a log to file logic to the script to check everything went well !

19 Responses
Add your response

Doesn't work for me.
Doing var_dump of response i get 'Token not valid'.

over 1 year ago ·

Hi,
Works fine for me.
Double check if your login/pass array("email" => "YOURADMINEMAIL","passwd" => "YOURADMINPASS" and check your PSCookie.txt file, the directry should be writable

over 1 year ago ·

I had solved the problem of the token, thank you anyway for your reply, but know i've another problem.

I adapted the script to recognize entities (products or combinations) and to work with existing csv file generated by previously executed cronjob.
I was able to make the script works only if I put it in the same folder of csv files ("$adminUrl/import").

Giving in output "$request" I get the import page with the error ".csv file unreadable".

over 1 year ago ·

Solved passing the basename of csv url.

over 1 year ago ·

Hi,
I'm not technical person and affraid of code that may not work or even worse - can act unexpectedly and damage my database.
I use a kind of cron tool in Store Manager for Prestashop, it is it's addon called Automated products import.
It can do updates of your existing products as well as import new ones from third-party storage place on daily, weekly or monthly bases.
There is 30-days free trial as well. You can find it at the same web-site as Store Manager. This article will explain how Automated products import can help you - http://www.prestashopmanager.com/useful-articles/how-to/how-to-accomplish-prestashop-cron-import-with-automated-product-import-addon/

over 1 year ago ·

Hello Baptiste, it worked one time for me but now I have an error "Clé de sécurité invalide" on my pages everytime i try to restart the cron. Any idea of where it could come from?
Thanks

over 1 year ago ·

Thanks for this nice little snippet. Works smoothly

over 1 year ago ·

Hello i don't understand very well how i can use this script.

First i create a file named script.php and in this i put the first code that you have posted.

Second i create a file named class.PSRequest.php and i put the second code.

So what is the directory then i must put these files?

And how i can run this script manually?

Thank you for answer and for the code.

over 1 year ago ·

Hi prontier,

you can put the scripts anywhere on your server, but the directory should be writeable and the main php script should be executable by the owner.

Then launch the main script like that :

> /usr/bin/php /path/to/my_script.php

Note that i didn't test it with the new prestashop 1.6

over 1 year ago ·

Thanks for your code.
I have modified your code because it doesn't work to my.
Your code doesn't send csv file by post to prestashop server.

This is my code:
https://coderwall.com/p/fwoaqq

over 1 year ago ·

Hello
Any body have same script for prestashop 1.6 or Any one tried same script with 1.6 ?

over 1 year ago ·

Hi all, in prestashop 1.6 i've got always invalid token, any suggest?

over 1 year ago ·

This script (or my version of this script https://coderwall.com/p/fwoaqq) works for prestashop 1.6.
Token invalid is because the login is failed or the script that split the response of the login page don't catch the token. Try to show all the response of login action.

over 1 year ago ·

Hi croustibat,

I tried your solution and magicianred's one, to import Attributes (entity = 2), but I keep on having the same issue : _webpage is desperately void, thus preventing an AdminImport token to be retrieved. I tried using the token provided by the call to AdminLogin but i still can't import anything.
Any idea ?

Regards

over 1 year ago ·

Here add this file ? Also i not found this class.PSRequest.php...

over 1 year ago ·

Hello,

FYI, it works with Prestashop 1.6.0.X !

over 1 year ago ·

how to know file is completed !!!

over 1 year ago ·

Hi i'm trying to set this script on my domain i get token but it doesn't enter in prestashop adin? someone can explain me why? thanks a lot

over 1 year ago ·

My modified version for prestashop 1.6.1.7

http://pastebin.com/YYMdkZj1

over 1 year ago ·