I'm trying to create an order with Magento SOAP API v1 and having issue when adding bundled products to the cart. I'm able to get an order through correctly with simple products but I'm confused about adding bundled products.
// The Products Array with Bundle
$products = array(
array(
"product_id" => "38914",
"qty" => "1",
"bundle_option" => array(
"18194" => "20360",
),
"related_product" => null,
"bundle_qty" => array("20360" => "1"),
"options" => array(
"0" => array(
"key" => "3328",
"value" => "4494",
),
"1" => array(
"key" => "3329",
"value" => null,
),
"2" => array(
"key" => "3339",
"value" => null,
),
)
)
);
// Get an API session
$client = new \SoapClient('magentoinstallation/index.php/api/soap/?wsdl');
$session = $client->login('user', 'password');
//Create the Cart
$cart = $client->call( $session, 'cart.create');
// add the products
$resultCartProductsAdd = $client->call( $session, "cart_product.add", array( $cart, $products ) );
I've tried many different formats and getting errors
Selected required options are not available
Please specify product option(s).
Any assistance or suggestions would be greatly appreciated.
I figured out a way to add a bundle product to cart via SOAP.
The values within the key bundle_option must be the ids of the models for the options (bundle/selection) (not the product ids). The keys must be the id for the option (I assume that's already correct in your example)
$products = array(
array(
"product_id" => "38914",
"qty" => "1",
"bundle_option" => array(
"18194" => "20360", // <-- THE VALUE MUST BE THE ID OF THE CORRESPONDING "bundle/selection" MODEL, INSTEAD OF THE PRODUCT'S ID
),
// ...
);
Also the key for the bundle quantities should be bundle_option_qty instead of bundle_qty.
Propably the availability of the bundled products will disturb your process, so ensure the products are all salable.
I tried it successfully with the sample data of magento and this snippet
$client = new \SoapClient('magentoinstallation/index.php/api/soap/?wsdl');
$session = $client->login('testuser', 'password');
$products = array(
array(
"product_id" => 158,
"qty" => "1",
"bundle_option" => array(
1 => 2, // 1 is the option id, 2 is the bundle/selection id
),
)
);
$cart = $client->call($session, 'cart.create', array('default'));
$resultCartProductsAdd = $client->call($session, "cart_product.add", array($cart, $products));
I retried my answer and found an important point to recognize.
SELECT A STORE ;-)
Just use
$cart = $client->call($session, 'cart.create', array('default'));
instead of
$cart = $client->call($session, 'cart.create');
(for more details please check the API specs: http://www.magentocommerce.com/api/soap/checkout/cart/cart.create.html)
After changing this, it was simple to add any bundle product, how described above
Related
Here is how i set data for custom options of simple product
$arrProducts = array(
array(
"product_id" => 8,
"qty" => 1,
"options" => array(
'1' => 'cheese',
'2' => 'tomato'
)
)
)
);
but i receive an error
Please specify the product required option(s).
you need to set the data in little bit different:
please see explain here.
and here .
Good Luck!
I've been looking all over the web but I can't seem to find any examples and I've tried it but failed. I am using version 2 of the api and I want to find product that filters by a customer attribute like so...
$filter = array(
array(
'key'=>'custom_attribute',
'value'=>"463"
)
);
$products = $client->catalogProductList($session,array(
'filter'=>$filter
));
But I am getting all the products and not the specific product I am looking for. Is there anything I am doing wrong ? Is there anything I am missing ??
Try following code.
$complexFilter = array (
'complex_filter' => array(
array(
'key' => 'custom_attribute',
'value' => array(
'key' => 'eq',
'value' => '463'
)
)
)
);
$products = $client->catalogProductList($session, $complexFilter);
I am working with the magento api and I have run into a bit of an issue with creating an order. I have been able to get everything up to creating the order to work correctly. The issue that I am seeing is when I call the method to create the order I always get the exception: Credit card number mismatch with credit card type.
I am running Magento ver. 1.6.2.0
I have verified that the card I am testing with works via the magento frontend.
Any help with this is greatly appreciated.
This is the test code that I am using:
<?php
$proxy = new SoapClient('http://localhost/index.php/api/soap/?wsdl');
$sessionId = $proxy->login('shopapi', 'test123');
// Create a quote, get quote identifier
$shoppingCartId = $proxy->call( $sessionId, 'cart.create');
// Set customer, for example guest
$customerAsGuest = array(
"firstname" => "testFirstname",
"lastname" => "testLastName",
"email" => "test#test.com",
//"website_id" => "0",
//"store_id" => "0",
"mode" => "guest"
);
$resultCustomerSet = $proxy->call($sessionId, 'cart_customer.set', array( $shoppingCartId, $customerAsGuest) );
// Set customer addresses, for example guest's addresses
$arrAddresses = array(
array(
"mode" => "shipping",
"firstname" => "testFirstname",
"lastname" => "testLastname",
"company" => "testCompany",
"street" => "testStreet",
"city" => "testCity",
"region" => "CA",
"postcode" => "90049",
"country_id" => "US",
"telephone" => "0123456789",
"fax" => "0123456789",
"is_default_shipping" => 0,
"is_default_billing" => 0
),
array(
"mode" => "billing",
"firstname" => "testFirstname",
"lastname" => "testLastname",
"company" => "testCompany",
"street" => "testStreet",
"city" => "testCity",
"region" => "CA",
"postcode" => "90049",
"country_id" => "US",
"telephone" => "0123456789",
"fax" => "0123456789",
"is_default_shipping" => 0,
"is_default_billing" => 0
)
);
$resultCustomerAddresses = $proxy->call($sessionId, "cart_customer.addresses", array($shoppingCartId, $arrAddresses));
// add products into shopping cart
$arrProducts = array(
array(
"product_id" => "1",
"qty" => 1
)
);
$resultCartProductAdd = $proxy->call($sessionId, "cart_product.add", array($shoppingCartId, $arrProducts));
// get list of products
$shoppingCartProducts = $proxy->call($sessionId, "cart_product.list", array($shoppingCartId));
// set payment method
$paymentMethod = array(
"method" => "authorizenet",
"cc_type" => 'MC',
"cc_number" =>'5555555555554444' ,
"cc_exp_month" => 9,
"cc_exp_year" => 2014,
"cc_cid" => 123
);
$resultPaymentMethod = $proxy->call($sessionId, "cart_payment.method", array($shoppingCartId, $paymentMethod));
// create order
$resultOrderCreation = $proxy->call($sessionId,"cart.order",array($shoppingCartId));
var_dump($resultOrderCreation);
?>
Your call to cart_payment.method is succeeding, according to your post, so the CC number is validating to be a MC card, as expected.
The problem is that Magento, due to PCI concerns, does NOT save the CC number in the database (in most cases).
So, as you are sending payment details, along with CC number and CID, in one request and then creating the order in another, the state is lost and the CC number and CID are blanked out.
When the order is created, the payment data is validated a second time and when that happens, it has an empty CC number with a type of MC, causing the fault you see.
Unfortunately, I do not see a way to make cart.order accept payment data as a work around.
You could write a module to extend the checkout APIs with a new method that does both steps in a single call and that would likely solve the problem.
I ran into this issue as well. My solution was to create a custom SOAP endpoint which handled all of the order creation and submission logic at once without multiple API calls.
Even this way, I was getting card type mismatch exceptions.
The trick was once I set the payment info, collect totals, and save quote, with the getPayment->importData method, it seems to forget the card info. Probably for (not the best way to handle) PCI-DSS compliance.
To solve it, I added another getPayment->importData line after saving the quote, before submitting the order.
This is achieved without changing any of the core files.
See example:
public function customCheckout($checkoutData=false)
{
if(!$checkoutData){
Mage::throwException("No checkout data received.");
}
if(!json_decode($checkoutData)){
Mage::throwException("Bad checkout data received.");
}
$data = json_decode($checkoutData);
$email = 'email#email.cc';
// get the basic store info to associate with order
$websiteId = Mage::app()->getWebsite()->getId();
$store = Mage::app()->getStore();
// begin checkout with a quote
$quote = Mage::getModel('sales/quote')->setStoreId($store->getId());
// set customer by email
$customer = Mage::getModel('customer/customer')
->setWebsiteId($websiteId)
->loadByEmail($email);
// handle customer not exists by creating a new customer
if($customer->getId() == ''){
$customer = Mage::getModel('customer/customer');
$customer->setWebsiteId($websiteId)
->setStore($store)
->setFirstName("Bob")
->setLastName("Loblaw")
->setEmail($email)
->setPassword('password');
$customer->save();
}
// assign customer to SO quote
$quote->assignCustomer($customer);
// do we want to send a confirmation email to the customer?
// my guess is we would handle that in a separate service.
$quote->setSendConfirmation(0);
// add products to quote
foreach($data->products as $item){
$product = Mage::getModel('catalog/product')->load($item->id);
$quote->addProduct($product,new Varien_Object(array('qty'=>$item->qty)));
}
// set SO billing address
$billingAddress = $quote->getBillingAddress()->addData(array(
'customer_address_id' => '',
'prefix' => '',
'firstname' => $data->customer->firstName,
'middlename' => '',
'lastname' => $data->customer->lastName,
'suffix' => '',
'company' => '',
'street' => array(
'0' => 'street1',
'1' => 'street2'
),
'city'=>'city',
'country_id'=>'US',
'region'=>'WA',
'postcode'=>'98101',
'telephone' => '425-425-4254',
'fax' => '789-789-7897',
'vat_id' => '',
'save_in_address_book' => 0
));
// set SO shipping address, this will probably be the location of sale, on-site
$shippingAddress = $quote->getShippingAddress()->addData(array(
'customer_address_id' => '',
'prefix' => '',
'firstname' => $data->customer->firstName,
'middlename' => 'middle',
'lastname' => $data->customer->lastName,
'suffix' => '',
'company' => '',
'street' => array(
'0' => 'street1',
'1' => 'street2'
),
'city'=>'city',
'country_id'=>'US',
'region'=>'WA',
'postcode'=>'98201',
'telephone' => '425-425-4254',
'fax' => '789-789-7897',
'vat_id' => '',
'save_in_address_book' => 0
));
// set shipping method, if it's sold on site we aren't charging for delivery
$shipMethod='freeshipping_freeshipping';
$shippingAddress->setCollectShippingRates(true)
->collectShippingRates()
->setShippingMethod($shipMethod)
->setPaymentMethod($data->payment->method);
// set payment method
$quote->getPayment()->importData(array(
'method' =>$data->payment->method,
'cc_type' =>$data->payment->type,
'cc_number' =>$data->payment->number,
'cc_exp_year' =>$data->payment->expYear,
'cc_exp_month'=>$data->payment->expMonth,
));
// collect totals, save quote
$quote->collectTotals()->save();
// turn the quote into an order
$service = Mage::getModel('sales/service_quote',$quote);
// set payment method A SECOND TIME!!!!!!!!!!!!!
$quote->getPayment()->importData(array(
'method' =>$data->payment->method,
'cc_type' =>$data->payment->type,
'cc_number' =>$data->payment->number,
'cc_exp_year' =>$data->payment->expYear,
'cc_exp_month'=>$data->payment->expMonth,
));
$service->submitAll();
$increment_id = $service->getOrder()->getRealOrderId();
$quote = $customer = $service = null;
$retval = new stdClass;
$retval->orderId = $increment_id;
return json_encode($retval);
}
I have never done successful API transactions to the payment method code authorizenet. This only always succeeds via frontend, not sure why.. nor have I had time to investigate why. Although what I have always done instead is to use authorizenet_direct post instead. My reasoning behind this / how I stumbled upon this is that the same also applies to the Paypal payment methods. API seems to only work with paypal_direct or paypaluk_direct. Try it! it should work. At the very least, this works for me.
$paymentMethod = array(
"method" => "authorizenet_directpost",
"cc_type" => 'MC',
"cc_number" =>'5555555555554444' ,
"cc_exp_month" => 9,
"cc_exp_year" => 2014,
"cc_cid" => 123
);
Actually I just discovered a way to take authorize.net payments via the API.
First in /app/code/core/Mage/Payment/Model/Method/Cc.php, uncomment the line about saving the cid, so the function look like this on line 65
public function prepareSave()
{
$info = $this->getInfoInstance();
if ($this->_canSaveCc) {
$info->setCcNumberEnc($info->encrypt($info->getCcNumber()));
}
$info->setCcCidEnc($info->encrypt($info->getCcCid()));
$info->setCcNumber(null)
->setCcCid(null);
return $this;
}
And then in the main model file of your payment method, make sure the variable is set to:
protected $_canSaveCc = true;
I've tested 2 payment methods using this and both work fine via API now.
this is my solution:
goto /app/code/core/Mage/Payment/Model/Method/Cc.php
and see function :
public function prepareSave()
{
$info = $this->getInfoInstance();
if ($this->_canSaveCc) {
$info->setCcNumberEnc($info->encrypt($info->getCcNumber()));
}
//$info->setCcCidEnc($info->encrypt($info->getCcCid()));
$info->setCcNumber(null)
->setCcCid(null);
return $this;
}
only comment line :
$info->setCcNumber(null)
->setCcCid(null);
I'm currently using the MailChimp API for PHP, version 1.3.1 (http://apidocs.mailchimp.com/api/downloads/#php)
I've set up a list in MailChimp, and would like to dynamically add:
Subscribers to the list (done: $objMailChimp->listBatchSubscribe($strMailingListID, ...))
Interest Groupings (done: $objMailChimp->listInterestGroupingAdd($strMailingListID, ...))
Interest Groups into those Groupings (done: $objMailChimp->listInterestGroupAdd($strMailingListID, ...))
Subscribers assigned to relevant Groups (not done)
The API (http://apidocs.mailchimp.com/api/1.3/#listrelated) is somewhat unclear on how to add a subscriber to an interest group - does anyone here have any ideas?
As of version 2.0 of MailChimp's API, this should work:
$merge_vars = array(
'GROUPINGS' => array(
array(
'name' => "GROUP CATEGORY #1", // You can use either 'name' or 'id' to identify the group
'groups' => array("GROUP NAME","GROUP NAME")
),
array(
'name' => "GROUP CATEGORY #2",
'groups' => array("GROUP NAME")
)
)
);
Source: http://apidocs.mailchimp.com/api/2.0/lists/subscribe.php
Using a barebones PHP wrapper (https://github.com/drewm/mailchimp-api/) you can then send this to MailChimp via either the lists/subscribe or lists/batch-subscribe:
$MailChimp = new MailChimp('API_KEY');
$result = $MailChimp->call('lists/subscribe', array(
'id' => 'LIST ID',
'email' => array('email'=>'trevor#example.com'),
'merge_vars' => $merge_vars
));
For MailChimp API v3
As of v3, 'groupings' has changed to 'interests'.
You have to find out the ID of the group (interest) that you are wanting to add to. Unfortunately this cannot be found anywhere on the MailChimp dashboard.
The easiest way to find out the 'interest' ID (rather than creating a script) is to go to the MailChimp playground and then, after entering in your API key, route to...
lists > the list in question > interest-categories (in the sub-resources dropdown)
then...
interests (in the sub-resources dropdown) for interest category
then...
Click through to the interest and refer to the 'id' field, ignoring the other ID fields
OR
lists > the list in question > members (in the sub-resources dropdown)
then...
load (in the actions dropdown) for any member
or
Create Members (button)
The page will load the member's details. Scroll down until you see the 'interests' array/object. There you will see the IDs. Notice they can be set to true or false.
You will have to figure out which ID relates to what 'group'/'interest' by going about the previous method or making the call, and then looking at the member's details via your MailChimp dashboard.
So when it comes to actually making the POST call ('member' create), you would want something on the lines of...
{
"email_address":"example#freddiesjokes.com",
"status":"subscribed",
"interests": {
"b8a9d7cbf6": true,
"5998e44916": false
},
# ADDITIONAL FIELDS, IF REQUIRED...
"merge_fields":{
"FNAME": "foo bar",
"LNAME": "foo bar",
"MERGE3": "foo bar",
"MERGE4": "foo bar"
}
}
A PUT call ('member' edit) example...
{
"interests": {
"b8a9d7cbf6": false,
"5998e44916": true
}
}
It seems that you must declare every 'interest', and state whether it is true or false.
I could not get the other answers on this page to work. Here's the merge vars that I had to use:
$merge_vars = array(
'GROUPINGS' => array(
0 => array(
'id' => "101", //You have to find the number via the API
'groups' => "Interest Name 1, Interest Name 2",
)
)
);
Use GROUPINGS merge var:
Set Interest Groups by Grouping. Each element in this array should be
an array containing the "groups" parameter which contains a comma
delimited list of Interest Groups to add. Commas in Interest Group
names should be escaped with a backslash. ie, "," => "\," and either
an "id" or "name" parameter to specify the Grouping - get from
listInterestGroupings()
Here's the code I got to work
require_once 'MCAPI.class.php';
require_once 'config.inc.php'; //contains apikey
// use this once to find out id of interest group List
//$retval = $api->listInterestGroupings($listId);
//echo '<pre>';
//print_r($retval);
//echo '</pre>';
//die();
$emailAddress = 'info#example.com';
//You have to find the number via the API (id of interest group list)
$interestGroupListId = FILLMEIN;
$api = new MCAPI($apikey);
// Create an array of Interest Groups you want to add the subscriber to.
$mergeVars = array(
'GROUPINGS' => array(
0 => array(
'id' => $interestGroupListId,
'groups' => "FILL IN GROUP NAMES",
)
)
);
// Then use listUpdateMember to add them
$retval = $api->listUpdateMember($listId, $emailAddress, $mergeVars);
if ($api->errorCode){
echo "Unable to update member info!\n";
echo "\tCode=".$api->errorCode."\n";
echo "\tMsg=".$api->errorMessage."\n";
} else {
echo "Returned: ".$retval."\n";
}
This is a variation of Justins answer but having tried all the above this is the only one I could get to work with DrewM's MailChimp wrapper
$merge_vars = array(
'GROUPINGS' => array(
0 => array(
'id' => '[GROUP_LIST_ID]', // need grouping ID
'name' => '[OR_GROUP_LIST_NAME]', // or name instead
'groups' => array( '[GROUP_NAME_1]', '[GROUP_NAME_2]' )
)
),
);
$mc = new MailChimp('[YOUR_MAILCHIMP_API]');
$mc->call(
'lists/subscribe', array(
'id' => '[YOUR_LIST_ID]', // list ID
'email' => array( 'email' => 'someone#something.com'),
'merge_vars' => $merge_vars,
'double_optin' => true,
'update_existing' => true,
'replace_interests' => false, // do you want to add or replace?
'send_welcome' => false,
)
);
If you are unsure of your groups lists ID and wish to use it you can call:
$current_groupings = $mc->call( 'lists/interest-groupings', array(
'id' => '[GROUP_LIST_ID]',
) );
var_dump($current_groupings);
Also please note optional but very important last parameter of listUpdateMember, by default replace_interests it set to true so it will overwrite any subscription the user you are updating could have had in the past. If you want to add new ones not touching previous ones just pass the new group name you wanna add and set replace_interests to false.
$api = new MailChimp('API_KEY');
$pArray = array('GROUPINGS'=>array(
array('name'=>'GROUP CATEGORY', 'groups'=>'group1,group2'),
)
);
if (is_array($pArray)) {
$api->listUpdateMember($pListId, $pEmail, $pArray, '', false);
}
Example using DrewM's MailChimp wrapper and shorthand syntax for arrays (PHP 5.4+) add to groups:
$merge_vars = [
'GROUPINGS' => array(
0 => [
'id' => 12345, // need grouping ID
'name' => 'Interests', // or name instead
'groups' => [ 'cars', 'trucks' ]
]
]
];
$mc = new MailChimp('API_KEY');
$mc->call(
'lists/subscribe', [
'id' => '9876', // list ID
'email' => array[ 'email' => 'example#abc.com' ],
'merge_vars' => $merge_vars,
'double_optin' => true,
'update_existing' => true,
'replace_interests' => false, // do you want to add or replace?
'send_welcome' => false,
]
);
You need grouping 'name' OR 'id', both are not needed. To get grouping ID use: lists/interest-groupings
I'm generating custom options for products in magento with the following:
$options = array();
$options = array(
'title' => 'Select Options',
'type' => 'radio',
'is_require' => 1,
'sort_order' => 0,
'values' => array()
);
$options['values'][] = array(
'title' => $customAttributeString,
'price' => 0.00,
'price_type' => 'fixed',
'sku' => $uniqueId,
'sort_order' => '1'
);
$id = Mage::getModel('catalog/product')->getIdBySku($sku);
$product = Mage::getModel('catalog/product')->load($id);
if(!$product->getOptionsReadonly()) {
$product->setProductOptions(array($options));
$product->setCanSaveCustomOptions(true);
$product->save();
}
I have this running in a loop, with a different SKU everytime and when I run my loop once, it generates custom options for the first product just fine, the second product has its own custom options, and the first products custom options, and the third product has custom options for all three, etc.. could anyone give me some insight on why this is happening?
Sorry for the late response but as Magento manage the product_option as a Singleton, you need to reset it on each iteration :
Mage::getSingleton('catalog/product_option')->unsetOptions();
Hope this helps.
Guillaume
$product->setProductOptions(array($option));
Notice, that you're setting not $options but $option (without "s" at the end). Maybe it intersects with some of your variables not shown in code snippet.
Also
$options = array();
is useless here, just remove it
It would be nicer, if you include iteration cycle and initialization of $customAttributeString, $sku, $uniqueId to you code sample there.
Mage::getSingleton('catalog/product_option')->unsetOptions();
Work fine just before the loop iteration
Atif