I'm not a big expert with PrestaShop but this is what I would like to achieve: Everytime a customer confirms an order for a particular product, I would like to send an http request to another server to start the production of the product.
This is what I have in mind:
Create a file in /override/controlers/front/OrderConfirmationController.php
class OrderConfirmationController extends OrderConfirmationControllerCore
{
public function initContent()
{
parent::initContent();
$url = 'http://server.com/path';
$data = array('key1' => 'value1', 'key2' => 'value2');
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: application/x-www-form-urlencoded\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
}
}
The issue is that I need certain specifications from the products (size, color, ...) but not all types of products will be sent to that production center.
I am using version 1.6.1.1
Thanks for your help!
Quentin
take a look into init() method of controller that you override
/controllers/front/OrderConfirmationController.php
there you may see:
$order = new Order((int)($this->id_order));
in child controller you have access to Order object, so:
$products = $order->getProducts();
will to get you products list.
Related
i'm new to laravel and i'm facing a painful problem.
I'm using Crinsane/LaravelShoppingcart in my ecommerce api and i'm trying to send a post request with axios in vuejs that adds a product to the cart by sending the product id and the quantity. The problem is the id and quantity are not reaching the application although i'm pretty sure i specified the correct route link in axios and i'm getting "No query results for model [App\Product]." which i assume means that the controller function that handles the request is working but the id is not being sent/transformed to the resource collection. I don't know if the problem is with the package i'm using or the code or something else.
this is axios request
addCart(item) {
axios
.post('/api/cart/add', item)
.then(response => (response.data.data))
.catch(error => console.log(error.response.data))
this is the route :
Route::post('cart/add', [
'uses' => 'ShoppingController#store',
'as' => 'cart.add'
]);
this is the cart collection
public function toArray($request)
{
return [
'id' => $this->id,
'qty' => $this->qty
];
}
this is the controller
public function store(){
$pdt = Product::findOrFail(request()->id);
$cart = Cart::add([
'id' => $pdt->id,
'name' => $pdt->name,
'qty' => request()->qty,
'price' => $pdt->price
]);
and this is the product model
class Product extends Model
{
protected $fillable = [
'name', 'description', 'image', 'category', 'quantity', 'price', 'sold','remaining','rating', 'bestSelling', 'featured'
];
}
Thank you in advance
The problem seems to be in your controller.
From the docs:
To obtain an instance of the current HTTP request via dependency injection, you should type-hint the Illuminate\Http\Request class on your controller method.
Try this:
public function store(Request, $request){
// Make sure the 'id' exists in the request
if ($request->get('id')) {
$pdt = Product::find($request->get('id'));
if ($request->get('qty')) {
$qty = $request->get('qty')
}
$cart = Cart::add([
'id' => $pdt->id,
'name' => $pdt->name,
'qty' => $qty,
'price' => $pdt->price
]);
}
Then, at the top of your controller, add:
use Illuminate\Http\Request;
So i found that it needed a json object to work and i had to put this code at the end of the store method :
return response()->json(['cart' => $cart], 201);
I am trying to get sessionid by using ebay Trading API . I am able to get session id successfully by using Curl but as soon as i try to fetch session id via Guzzle Http client, get below error in response from ebay
FailureUnsupported API call.The API call "GeteBayOfficialTime" is
invalid or not supported in this release.2ErrorRequestError18131002
I suppose there's some issues with the way i am using GuzzleHttp client . I am currently using GuzzleHttp v6 and new to this . Below is the code i am using to get session id by calling actionTest function
public function actionTest(){
$requestBody1 = '<?xml version="1.0" encoding="utf-8" ?>';
$requestBody1 .= '<GetSessionIDRequest xmlns="urn:ebay:apis:eBLBaseComponents">';
$requestBody1 .= '<Version>989</Version>';
$requestBody1 .= '<RuName>test_user-TestAs-Geforc-ldlnmtua</RuName>';
$requestBody1 .= '</GetSessionIDRequest>';
$headers = $this->getHeader();
$client = new Client();
$request = new Request('POST','https://api.sandbox.ebay.com/ws/api.dll',$headers,$requestBody1);
$response = $client->send($request);
/*$response = $client->post('https://api.sandbox.ebay.com/ws/api.dll', [
'headers' => $headers,
'body' => $requestBody1
]);*/
echo $response->getBody();die;
}
public function getHeader()
{
$header = array(
'Content-Type: text/xml',
'X-EBAY-API-COMPATIBILITY-LEVEL: 989',
'X-EBAY-API-DEV-NAME: a4d749e7-9b22-441e-8406-d3b65d95d41a',
'X-EBAY-API-APP-NAME: TestUs-GeforceI-SBX-345ed4578-10122cfa',
'X-EBAY-API-CERT-NAME: PRD-120145f62955-96aa-4d748-b1df-6bf4',
'X-EBAY-API-CALL-NAME: GetSessionID',
'X-EBAY-API-SITEID: 203',
);
return $header;
}
Plz suggest the possible shortcoming in the way i am making request . I already tried/modified the guzzle request call by referring various reference site and guzzle official doc but error remained same .
You need to pass an associative array of headers as explained in the documentation.
public function getHeader()
{
return [
'Content-Type' => 'text/xml',
'X-EBAY-API-COMPATIBILITY-LEVEL' => '989',
'X-EBAY-API-DEV-NAME' => '...',
'X-EBAY-API-APP-NAME' => '...',
'X-EBAY-API-CERT-NAME' => '...',
'X-EBAY-API-CALL-NAME' => '...',
'X-EBAY-API-SITEID' => '203',
];
}
In case you are interested there is an SDK available that simplifies the code. An example of how to call GetSessionID is shown below.
<?php
require __DIR__.'/vendor/autoload.php';
use \DTS\eBaySDK\Trading\Services\TradingService;
use \DTS\eBaySDK\Trading\Types\GetSessionIDRequestType;
$service = new TradingService([
'credentials' => [
'appId' => 'your-sandbox-app-id',
'certId' => 'your-sandbox-cert-id',
'devId' => 'your-sandbox-dev-id'
],
'siteId' => '203',
'apiVersion' => '989',
'sandbox' => true
]);
$request = new GetSessionIDRequestType();
$request->RuName = '...';
$response = $service->getSessionID($request);
echo $response->SessionID;
I have built an API and an application that uses that API. Everything was working but now, for some reason, I get a 400 Bad Request response. I am not sure if I changed something in the code so I wanted to double check it was correct.
So my API call is this
$client = new GuzzleHttp\Client();
$jsonData = json_encode($data);
$req = $client->request('POST', 'https://someurl.com/api/v1/createProject', [
'body' => $jsonData,
'headers' => [
'Content-Type' => 'application/json',
'Content-Length' => strlen($jsonData),
]
]);
$output = $req->getBody()->getContents();
The API has a route set up correctly which uses post. The function it calls is correct, and I have changed it for testing to simply return
return response()->json(["Success", 200]);
When I test the API out within Postman, I can see that Success is returned. When I test the API within the other application I have built, I dont even see a POST request within the console, I am just displayed a Laravel error 400 Bad Request.
What could be the cause of this issue?
Thanks
Update
I have changed the request to this
$data= json_encode($data);
$req = $client->post('https://someurl.com/api/v1/createProject', [
'body' => $data
]);
If I output $data after it has been encoded, I get something like this
{
"projectName":"New Project",
"clientName":"Test Client",
}
Within the controller function of the API that is being called, I simply do
return response()->json(['name' => $request->input('clientName')]);
The 400 error has now gone, but I now get null returned to me
{#326 ▼
+"name": null
}
Request is being injected into the function as it should be. Should I be returning the data in a different way?
Thanks
Probably you did $ composer update and Guzzle updated.
So if you are using newest Guzzle (guzzlehttp/guzzle (6.2.2)) you do POST request:
$client = new GuzzleHttp\Client();
$data = ['name' => 'Agent Smith'];
$response = $client->post('http://example.dev/neo', [
'json' => $data
]);
You do not need to specify headers.
To read response you do following:
$json_response = json_decode($response->getBody());
My full example (in routes file web.php routes.php)
Route::get('smith', function () {
$client = new GuzzleHttp\Client();
$data = ['name' => 'Agent Smith'];
$response = $client->post('http://example.dev/neo', [
'json' => $data,
]);
$code = $response->getStatusCode();
$result = json_decode($response->getBody());
dd($code, $result);
});
Route::post('neo', function (\Illuminate\Http\Request $request) {
return response()->json(['name' => $request->input('name')]);
});
or you could use following (shortened), but code above is "shorter"
$json_data = json_encode(['name' => 'Agent Smith']);
$response = $client->post('http://example.dev/neo', [
'body' => $json_data,
'headers' => [
'Content-Type' => 'application/json',
'Content-Length' => strlen($json_data),
]
]);
note: If you are running PHP5.6, change always_populate_raw_post_data to -1 (or uncomment the line) in php.ini and restart your server. Read more here.
In my case I was using public IP address in BASE_URL while I should have been using the private IP. From mac you can get your IP by going into system preferences -> network.
This is with Android + Laravel (API)
I'm new to Yii, and I'm trying to do my initial project the "right" way. I've created a CFormModel class that needs three fields to query for some data, a CForm config to construct the form, and a CController to tie it together (all given below).
The data request needs an account, and this can come from a couple of different places. I think retrieving it should be in the controller. However, I don't know how to get it into the form's hidden "account" field from the controller, so that it makes it to the arguments assigned to the CFormModel after submission. More generally, I know how to pass from CController to view script, but not to CForm. Is the registry (Yii::app()->params[]) my best bet?
I suppose I can just leave it out of the form (and required fields) and wait to populate it in the submit action (actionSummaries). Does that break the intention of CForm? Is there a best practice? Even taking this solution, can someone address the first issue, in case it comes up again?
Any other, gentle critique is welcome.
models/SummariesForm.php
class SummariesForm extends CFormModel
{
public $account;
public $userToken;
public $year;
public function rules () {...}
public function fetchSummary () {...}
static public function getYearOptions () {...}
}
views/account/select.php
<?php
$this->pageTitle=Yii::app()->name;
?>
<div class="form">
<?php echo $form->render(); ?>
</div>
controllers/AccountController.php
class AccountController extends CController
{
public $layout = 'extranet';
public function actionSelect ()
{
$model = new SummariesForm();
// retrieve account
require_once 'AccountCookie.php';
/*
*
* Here, I insert the account directly into the
* model used to build the form, but $model isn't
* available to selectForm.php. So, it doesn't
* become part of the form, and this $model doesn't
* persist to actionSummaries().
*
*/
$model->account = AccountCookie::decrypt();
if ($model->account === false) {
throw new Exception('Unable to retrieve account.');
}
$form = new CForm('application.views.account.selectForm', $model);
$this->render('select', array(
'form' => $form,
'account' => $model->account,
));
}
public function actionSummaries ()
{
$model = new SummariesForm();
if (isset($_POST['SummariesForm'])) {
$model->attributes = $_POST['SummariesForm'];
/*
*
* Should I just omit "account" from the form altogether
* and fetch it here? Does that break the "model"?
*
*/
if ($model->validate() === true) {
try {
$summaries = $model->fetchSummary();
} catch (Exception $e) {
...
CApplication::end();
}
if (count($summaries) === 0) {
$this->render('nodata');
CApplication::end();
}
$this->render('summaries', array('model' => $model, 'summaries' => $summaries));
} else {
throw new Exception('Invalid year.');
}
}
}
}
views/account/selectForm.php
<?php
return array(
'title' => 'Select year',
'action' => Yii::app()->createUrl('Account/Summaries'),
'method' => 'post',
'elements' => array(
'account' => array(
'type' => 'hidden',
'value' => $account,
),
'userToken' => array(
'type' => 'hidden',
'value' => /* get token */,
),
'year' => array(
'type' => 'dropdownlist',
'items' => SummariesForm::getYearOptions(),
),
),
'buttons' => array(
'view' => array(
'type' => 'submit',
'label' => 'View summaries',
),
),
);
The answer is NO to do what you asked. You can see $form variable which acted almost like array when it was passed from controller to view. The solution is you add more property $account into selectForm model and treat it like other elements. I don't think leaving the new field outside the form will be properly way if you want to submit its value also.
Edited:
I'm working on the Magento API and I got some questions...
I try to get all Product Names from a specific category at Magento.
here's my code for that:
<?php
$host = "www.host.tld/index.php";
$client = new SoapClient("http://".$host."/api/soap/?wsdl");
$apiuser= "user"; //webservice user login
$apikey = "pass"; //webservice user pass
try {
// Login
$sess_id= $client->login($apiuser, $apikey);
// Getting all products from category
$filters = array( 'category_ids' => array('107') );
$productList = $client->call($sess_id, 'catalog_category.assignedProducts', $filters);
//iterate and get all the product_id's and put it into one array
foreach($productList as $products => $values){
if (isset($values['product_id']) || array_key_exists('product_id', $values)) {
$product_ids[] = $values['sku'];
}
}
//Get product details from product_id
foreach($product_ids as $key => $values) {
$details = $client->call( $sess_id, 'product.info', array($values));
#echo $details['name'];
}
}
catch (Exception $e) { //while an error has occured
echo "==> Error: ".$e->getMessage();
exit();
}
?>
The main problem I have is, that the performance I get is not the best. For each "product name" I make one api-call for getting all products. Every time for each product. That's probably not so clever.
What can I optimize. Am I missing something?
I can imagine, that if I want to get the details from more than one category, my server will crash ;). We have about 1000 products in our shop.
Thanks for the help.
Try
$proxy = new SoapClient('http://magentohost/api/soap/?wsdl');
$sessionId = $proxy->login('apiUser', 'apiKey');
$filters = array(
'id' => array('in' => array(<product_id_1>, <product_id_2>, ...))
);
$products = $proxy->call($sessionId, 'product.list', array($filters));
If you need some extended info about product - you should alter magento code, see this my answer on the similar questionL Magento API v1- List prices for all products in one call
You can use to catalog_category.assignedProducts
Retrieve the list of products assigned to a required category.
try this if you are using SOAP V1:
$client = new SoapClient('http://magentohost/api/soap/?wsdl');
// If somestuff requires api authentification,
// then get a session token
$session = $client->login('apiUser', 'apiKey');
$result = $client->call($session, 'catalog_category.assignedProducts', '4');
var_dump($result);
// If you don't need the session anymore
//$client->endSession($session);
if you are using SOAP V2:
$proxy = new SoapClient('http://magentohost/api/v2_soap/?wsdl'); // TODO : change url
$sessionId = $proxy->login('apiUser', 'apiKey'); // TODO : change login and pwd if necessary
$result = $proxy->catalogCategoryAssignedProducts($sessionId, '4');
var_dump($result);
and the respond would be like this:
array
0 =>
array
'product_id' => string '1' (length=1)
'type' => string 'simple' (length=6)
'set' => string '4' (length=1)
'sku' => string 'n2610' (length=5)
'position' => string '1' (length=1)
1 =>
array
'product_id' => string '2' (length=1)
'type' => string 'simple' (length=6)
'set' => string '4' (length=1)
'sku' => string 'b8100' (length=5)
'position' => string '1' (length=1)