{"id":1889,"date":"2018-12-21T13:48:09","date_gmt":"2018-12-21T11:48:09","guid":{"rendered":"https:\/\/www.h-hennes.fr\/blog\/?p=1889"},"modified":"2018-12-21T13:48:09","modified_gmt":"2018-12-21T11:48:09","slug":"prestashop-passer-des-commandes-via-lapi","status":"publish","type":"post","link":"https:\/\/www.h-hennes.fr\/blog\/2018\/12\/21\/prestashop-passer-des-commandes-via-lapi\/","title":{"rendered":"Prestashop : Passer des commandes via l&rsquo;api"},"content":{"rendered":"<p>J&rsquo;ai r\u00e9cemment du faire des tests de commandes via les Api de Prestashop et je n&rsquo;ai pas trouv\u00e9 de script tout fait qui le permettait.<br \/>\nCelui-ci utilise la librairie fournie par Prestashop et disponible sur github : https:\/\/github.com\/PrestaShop\/PrestaShop-webservice-lib\/blob\/master\/PSWebServiceLibrary.php<\/p>\n<p>En voici donc un basique qui va effectuer les actions suivantes :<\/p>\n<ul>\n<li>R\u00e9cup\u00e9ration de l&rsquo;identifiant client ( cr\u00e9ation du client si n\u00e9cessaire )<\/li>\n<li>R\u00e9cup\u00e9ration de l&rsquo;identifiant de l&rsquo;adresse du client ( cr\u00e9ation si n\u00e9cessaire )<\/li>\n<li>Cr\u00e9ation d&rsquo;un panier<\/li>\n<li>Passage de la commande<\/li>\n<\/ul>\n<p>Ce script a \u00e9t\u00e9 ex\u00e9cut\u00e9 avec succ\u00e8s sur la version 1.7.3.3 de Prestashop et doit donc \u00eatre compatible avec les versions suivantes.<br \/>\nJe n&rsquo;ai pas constat\u00e9 de changement fondamentaux dans l&rsquo;api par rapport \u00e0 Prestashop 1.6, pour lequel il devrait \u00e9galement fonctionner ( en changeant les produits )<\/p>\n<p>N\u2019h\u00e9sitez pas \u00e0 partager vos retours d&rsquo;exp\u00e9riences sur l&rsquo;utilisation de l&rsquo;api de Prestashop<\/p>\n<pre lang=\"php\" escaped=\"true\">\r\n\r\nrequire_once('.\/PSWebServiceLibrary.php');\r\n\r\ntry {\r\n\r\n    $host = 'https:\/\/yourshop.com';\r\n    $apiKey = 'APIKEY';\r\n\r\n    $webService = new PrestaShopWebservice($host, $apiKey, false);\r\n\r\n    \/**\r\n     * On stocke ici les variables communes aux commandes cr\u00e9\u00e9s via l'api\r\n     *\/\r\n\r\n      $customerEmail = 'testmail3@yopmail.com'; \/\/Email du client ( A dynamiser dans le cadre d'une utilisation compl\u00e8te )\r\n      $carrierName = 'My carrier'; \/\/Nom du transporteur dans prestashop ( utilis\u00e9 pour r\u00e9cup\u00e9rer son identifiant )\r\n      $paymentLabel = 'Paiement par ch\u00e8que'; \/\/ Nom du mode de paiement\r\n      $paymentCode = 'ps_checkpayment'; \/\/Module de paiement utilis\u00e9\r\n                  \r\n    \/**\r\n     * Liste des produits qu'on souhaite ajouter au panier\r\n     *\/\r\n    $products = [\r\n        [\r\n            'reference' => 'demo_12',\r\n            'qty' => 3,\r\n        ],\r\n        [\r\n            'reference' => 'demo_19',\r\n            'qty' => 1,\r\n        ],\r\n        [\r\n            'reference' => 'demo_6',\r\n            'qty' => 2,\r\n            'combination' => [\r\n                'reference' => 'demo_6'\r\n            ]\r\n        ],\r\n    ];\r\n\r\n    \/\/Param\u00e8tres du client\r\n    $customerDatas = [\r\n        'firstname' => 'herve',\r\n        'lastname' => 'test',\r\n        'email' => 'testemaddil@yopmail.com',\r\n        'passwd' => 'mypassword',\r\n        'note' => 'Customer created with api',\r\n    ];\r\n\r\n    \/\/Param\u00e8tres de l'adresse\r\n    $addressDatas = [\r\n        'alias' => 'addresse api',\r\n        'id_customer' => $customerId,\r\n        'firstname' => 'herve',\r\n        'lastname' => 'test',\r\n        'address1' => 'rue des tests',\r\n        'address2' => 'encore rue des tests',\r\n        'postcode' => '67000',\r\n        'city' => 'strasbourg',\r\n        'phone' => '063656565',\r\n        'id_country' => 8,\r\n    ];\r\n\r\n\r\n    \/\/On regarde si le client existe\r\n    $searchCustomerXml = $webService->get([\r\n        'resource' => 'customers',\r\n        'filter' => ['email' => $customerEmail],\r\n    ]);\r\n\r\n    \/\/Si il existe on r\u00e9cup\u00e8re l'identifiant\r\n    if (!empty($searchCustomerXml->children()->children())) {\r\n        $customerId = (int)$searchCustomerXml->children()->children()[0]->attributes()['id'][0];\r\n    } \/\/Si il n'existe pas on le cr\u00e9\u00e9\r\n    else {\r\n        \/\/Cr\u00e9ation d'un client\r\n        $clientXml = $webService->get(['url' => $host . 'api\/customers?schema=blank']);\r\n        foreach ($clientXml->customer[0] as $nodeKey => $node) {\r\n            if (array_key_exists($nodeKey, $customerDatas)) {\r\n                $clientXml->children()[0]->$nodeKey = $customerDatas[$nodeKey];\r\n            }\r\n        }\r\n        $opt = array('resource' => 'customers');\r\n        $opt['postXml'] = $clientXml->asXML();\r\n        $resultXml = $webService->add($opt);\r\n        $customerId = (int)$resultXml->children()[0]->id;\r\n    }\r\n\r\n    \/\/R\u00e9cup\u00e9ration des adresses on part du principe qu'on r\u00e9cup\u00e8re la premi\u00e8re adresse du client si elle existe\r\n    \/\/On regarde si le client existe\r\n    $searchAddressXml = $webService->get([\r\n        'resource' => 'addresses',\r\n        'filter' => ['id_customer' => $customerId],\r\n    ]);\r\n    \r\n    \/\/Si il existe on r\u00e9cup\u00e8re l'identifiant de la premi\u00e8re adresse\r\n    if (!empty($searchAddressXml->children()->children())) {\r\n        $addressId = (int)$searchAddressXml->children()->children()[0]->attributes()['id'][0];\r\n    } \/\/Si il n'existe pas on le cr\u00e9\u00e9\r\n    else {\r\n\r\n        \/\/Cr\u00e9ation d'un client\r\n        $addressXml = $webService->get(['url' => $host . 'api\/addresses?schema=blank']);\r\n        foreach ($addressXml->address[0] as $nodeKey => $node) {\r\n            if (array_key_exists($nodeKey, $addressDatas)) {\r\n                $addressXml->children()[0]->$nodeKey = $addressDatas[$nodeKey];\r\n            }\r\n        }\r\n\r\n        $opt = array('resource' => 'addresses');\r\n        $opt['postXml'] = $addressXml->asXML();\r\n        $resultXml = $webService->add($opt);\r\n        $addressId = (int)$resultXml->children()[0]->id;\r\n    }\r\n\r\n    \/\/Cr\u00e9ation d'un panier\r\n    $cartXml = $webService->get(['url' => $host . 'api\/carts?schema=blank']);\r\n\r\n    \/\/D\u00e9finition des param\u00e8tres par d\u00e9faut du panier\r\n    \/\/Tout ces param\u00e8tres pourront \u00eatre r\u00e9cup\u00e9r\u00e9s de l'api en une fois et stock\u00e9s\r\n    $cartXml->cart->id_customer = $customerId;\r\n    $cartXml->cart->id_address_delivery = $addressId;\r\n    $cartXml->cart->id_address_invoice = $addressId;\r\n    $cartXml->cart->id_currency = 1; \/\/@Todo r\u00e9cup\u00e9rer via api\r\n    $cartXml->cart->id_lang = 1; \/\/@Todo r\u00e9cup\u00e9rer via api\r\n    $cartXml->cart->id_shop = 1; \/\/@Todo r\u00e9cup\u00e9rer via api\r\n    $cartXml->cart->id_shop_group = 1;\r\n\r\n    \/\/Identifiant du transporteur \u00e0 r\u00e9cup\u00e9rer dynamiquement ( peut bouger en \u00e9tant \u00e9dit\u00e9 dans le backoffice )\r\n    $carrierXml = $webService->get(['resource' => 'carriers', 'filter' => ['name' => $carrierName]]);\r\n\r\n    if (!empty($carrierXml->children()->children()[0]->attributes()['id'][0])) {\r\n        $id_carrier = (int)$carrierXml->children()->children()[0]->attributes()['id'][0];\r\n    } \/\/Si il n'existe pas on le cr\u00e9\u00e9\r\n    else {\r\n        exit('Mode de livraison existe pas');\r\n    }\r\n\r\n    $cartXml->cart->id_carrier = $id_carrier;\r\n\r\n    \/\/R\u00e9cup\u00e9ration de identifiants des produits\r\n    $productIds = array();\r\n    foreach ($products as $cartProduct) {\r\n        $productSearchXml = $webService->get([\r\n            'resource' => 'products',\r\n            'filter' => ['reference' => $cartProduct['reference']],\r\n        ]);\r\n\r\n        if (!empty($productSearchXml->children()->children()[0]->attributes()['id'][0])) {\r\n            $id_product = (int)$productSearchXml->children()->children()[0]->attributes()['id'][0];\r\n        } else {\r\n            \/\/Si pas de produit on ne peut pas continuer\r\n            continue;\r\n        }\r\n\r\n        if (isset($cartProduct['combination'])) {\r\n            $combinationSearchXml = $webService->get([\r\n                'resource' => 'combinations',\r\n                'filter' => ['reference' => $cartProduct['reference']],\r\n            ]);\r\n            if (!empty($combinationSearchXml->children()->children()[0]->attributes()['id'][0])) {\r\n                $id_product_attribute = (int)$combinationSearchXml->children()->children()[0]->attributes()['id'][0];\r\n            } else {\r\n                $id_product_attribute = 0;\r\n            }\r\n        } else {\r\n            $id_product_attribute = 0;\r\n        }\r\n        $productIds[] = [\r\n            'id_product' => $id_product,\r\n            'id_product_attribute' => $id_product_attribute,\r\n            'qty' => $cartProduct['qty']\r\n        ];\r\n    }\r\n\r\n    \/\/Insertion des lignes de produits\r\n    foreach ($productIds as $productId) {\r\n        $child = $cartXml->cart->associations->cart_rows->addChild('cart_row');\r\n        $child->id_product = $productId['id_product'];\r\n        $child->id_product_attribute = $productId['id_product_attribute'];\r\n        $child->quantity = $productId['qty'];\r\n        $child->id_adddress_delivery = $addressId;\r\n    }\r\n\r\n    \/\/Cr\u00e9ation du panier\r\n    $opt = array('resource' => 'carts');\r\n    $opt['postXml'] = $cartXml->asXML();\r\n    $addCartXml = $webService->add($opt);\r\n\r\n    \/\/Cr\u00e9ation d'une commande ( \u00e0 faire )\r\n    $orderXml = $webService->get(['url' => $host . 'api\/orders?schema=blank']);\r\n    \r\n    \/\/On d\u00e9fini les \u00e9l\u00e9ments de la commande sp\u00e9cifiques\r\n    $orderXml->order->valid = 1;\r\n    $orderXml->order->module = 'ps_checkpayment'; \/\/Module de paiement\r\n    $orderXml->order->payment = 'Paiement par cheque'; \/\/Lib\u00e9ll\u00e9 du mode de paiment\r\n    \r\n    \/\/Les \u00e9l\u00e9ments communs avec le panier sont r\u00e9cup\u00e9r\u00e9s depuis celui-ci\r\n    $orderXml->order->id_address_delivery = $addCartXml->cart->id_address_delivery;\r\n    $orderXml->order->id_address_invoice = $addCartXml->cart->id_address_invoice;\r\n    $orderXml->order->id_cart = $addCartXml->cart->id;\r\n    $orderXml->order->id_customer = $addCartXml->cart->id_customer;\r\n    $orderXml->order->id_carrier = $addCartXml->cart->id_carrier;\r\n    $orderXml->order->id_currency = $addCartXml->cart->id_currency;\r\n    $orderXml->order->id_shop = $addCartXml->cart->id_shop;\r\n    $orderXml->order->id_shop_group = $addCartXml->cart->id_shop_group;\r\n    $orderXml->order->id_lang = $addCartXml->cart->id_lang;\r\n    \r\n    \/\/ les lignes des produits sont aussi r\u00e9cup\u00e9r\u00e9es depuis le panier\r\n\r\n    $orderTotal = 0; \/\/Variable pour calculer le total de la commande\r\n    unset($orderXml->order->associations->order_rows->children()[0]); \/\/Suppression de ligne order_detail de d\u00e9mo\r\n    foreach ( $addCartXml->cart->associations->cart_rows->cart_row as $cartRow) {\r\n        \r\n        \/\/On ne traite pas les lignes vides\r\n        if ( $cartRow->id_product == 0 || $cartRow->id_product ==\"\")\r\n            continue;\r\n        \r\n        \/\/On r\u00e9cup\u00e8re les informations disponibles depuis le panier\r\n        $orderRow = $orderXml->order->associations->order_rows->addChild('order_row');\r\n        $orderRow->product_id = $cartRow->id_product;\r\n        $orderRow->product_attribute_id = $cartRow->id_product_attribute;\r\n        $orderRow->product_quantity = $cartRow->quantity;\r\n        \r\n        \/\/Pour le reste on le r\u00e9cup\u00e8re depuis les produits\r\n        $productXml = $webService->get(['url' => $host . 'api\/products\/'.$cartRow->id_product]);\r\n        $orderRow->product_name = $productXml->product->name;\r\n        $orderRow->product_reference = $productXml->product->reference;\r\n        $orderRow->product_price = $productXml->product->price;\r\n        \r\n        \/\/Ajout du montant du produit au total du panier ( Le prix HT * la qt\u00e9 * 1+ Taux de tva )\r\n        $orderTotal += ( (float)$productXml->product->price * (int)$cartRow->quantity ) * 1.20 ;\r\n    }\r\n    \r\n    \/\/Donn\u00e9es sp\u00e9cifiques \u00e0 la commande   \r\n    $orderXml->order->total_paid_real = $orderTotal; \/\/Montant pay\u00e9 r\u00e9ellement \r\n    $orderXml->order->total_paid = $orderTotal; \/\/Montant pay\u00e9 \r\n    \r\n    $orderXml->order->total_products = 1; \/\/Montant total produit ht ( obligatoire mais indicatif car recalcul\u00e9 automatiquement )\r\n    $orderXml->order->total_products_wt = 1; \/\/Montant total produit ttc ( obligatoire mais indicatif car recalcul\u00e9 automatiquement )\r\n    $orderXml->order->conversion_rate = 1; \/\/ Taux de conversion\r\n    \r\n    \r\n    \/\/Cr\u00e9ation de la commande\r\n    $opt = array('resource' => 'orders');\r\n    $opt['postXml'] = $orderXml->asXML();\r\n    $addOrderXml = $webService->add($opt);\r\n    \r\n    echo 'Cr\u00e9ation de la commande '.$addOrderXml->order->id;    \r\n} catch (PrestaShopWebserviceException $e) {\r\n    echo $e->getMessage();\r\n}\r\n<\/pre>\n<p>Des optimisations et des factorisations sont encore possibles mais cela donne d\u00e9j\u00e0 une bonne base fonctionnelle \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>J&rsquo;ai r\u00e9cemment du faire des tests de commandes via les Api de Prestashop et je n&rsquo;ai pas trouv\u00e9 de script tout fait qui le permettait. Celui-ci utilise la librairie fournie par Prestashop et disponible sur github : https:\/\/github.com\/PrestaShop\/PrestaShop-webservice-lib\/blob\/master\/PSWebServiceLibrary.php En voici donc un basique qui va effectuer les actions suivantes : R\u00e9cup\u00e9ration de l&rsquo;identifiant client ( [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[245],"tags":[240,516,383,542,104],"class_list":["post-1889","post","type-post","status-publish","format-standard","hentry","category-prestashop-2","tag-adresses","tag-api","tag-client","tag-commande","tag-prestashop","prestashop-1-5","prestashop-1-6","prestashop-1-7","prestashop-1-7-7","prestashop-1-7-8","prestashop-8-1"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/1889","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/comments?post=1889"}],"version-history":[{"count":3,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/1889\/revisions"}],"predecessor-version":[{"id":2018,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/posts\/1889\/revisions\/2018"}],"wp:attachment":[{"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/media?parent=1889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/categories?post=1889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.h-hennes.fr\/blog\/wp-json\/wp\/v2\/tags?post=1889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}