Programatically create customer and order in Magento with full blown One Page Checkout process under the hood

ordering

Its been a while since my last article. Figured I might write one before Google search punishes me :) -Recently I was working on a task that, among other things, required an order to be created programatically alongside with the customer and its billing and shipping address. Example I will demonstrate is just one way of doing things. If you have extra time on your hands, feel free to trace the code for more elegant solution.

For starters, lets create a customer and establish a login session right away for this newly created customer. Here is the code sample that does just that.

$customer = Mage::getModel('customer/customer');
//$customer  = new Mage_Customer_Model_Customer();
 
 
$password = '123456';
$email = 'ajzele@mymail.com';
 
$customer->setWebsiteId(Mage::app()->getWebsite()->getId());
$customer->loadByEmail($email);
//Zend_Debug::dump($customer->debug()); exit;
 
if(!$customer->getId()) {
 
	$customer->setEmail($email);
	$customer->setFirstname('Johnny');
	$customer->setLastname('Doels');
	$customer->setPassword($password);
}
 
try {
	$customer->save();
	$customer->setConfirmation(null);
	$customer->save();
 
	//Make a "login" of new customer
	Mage::getSingleton('customer/session')->loginById($customer->getId());
}
 
catch (Exception $ex) {
	//Zend_Debug::dump($ex->getMessage());
}	

You can run this code from anywhere in Magento (model, view, controller…), it should do the trick.

At this point we have created new customer and made him “look like” he is logged in, or shall I say we established a session with his new credentials.

Now lets add a shipping and billing address to customer. Remember, these are needed in order to do checkout. Here is the code that programatically adds the shipping and billing address. In my case, I am using same address for both shipping and billing. If you prefer you can extend the logic and create two separate addresses and make one default for billing, other for shipping.

//Build billing and shipping address for customer, for checkout
$_custom_address = array (
	'firstname' => 'Branko',
	'lastname' => 'Ajzele',
	'street' => array (
		'0' => 'Sample address part1',
		'1' => 'Sample address part2',
	),
 
	'city' => 'Osijek',
	'region_id' => '',
	'region' => '',
	'postcode' => '31000',
	'country_id' => 'HR', /* Croatia */
	'telephone' => '0038531555444',
);
 
$customAddress = Mage::getModel('customer/address')
//$customAddress = new Mage_Customer_Model_Address();
$customAddress->setData($_custom_address)
			->setCustomerId($customer->getId())
			->setIsDefaultBilling('1')
			->setIsDefaultShipping('1')
			->setSaveInAddressBook('1');
 
try {
	$customAddress->save();
}
catch (Exception $ex) {
	//Zend_Debug::dump($ex->getMessage());
}
 
Mage::getSingleton('checkout/session')->getQuote()->setBillingAddress(Mage::getSingleton('sales/quote_address')->importCustomerAddress($customAddress));

Now that we have a logged in newly created customer with assigned addresses, lets add some products to the cart in his name. Here is the sample code.

/* If we wish to load some product by some attribute value diferent then id */
$product = Mage::getModel('catalog/product')->getCollection()
	/* Remember, you can load/find product via any attribute, better if its attribute with unique value */
	->addAttributeToFilter('sku', 'some-sku-value')
	->addAttributeToSelect('*')
	->getFirstItem();
 
/* Do a full product load, otherwise you might get some errors related to stock item */
$product->load($product->getId());
 
$cart = Mage::getSingleton('checkout/cart');
 
/* We want to add only the product/products for this user and do so programmatically, so lets clear cart before we start adding the products into it */
$cart->truncate();
$cart->save();
$cart->getItems()->clear()->save();			
 
try {
	/* Add product with custom oprion? =>  some-custom-option-id-here: value to be read from database or assigned manually, hardcoded? Just example*/
	//$cart->addProduct($product, array('options'=> array('some-custom-option-id-here' => 'Some value goes here');
	$cart->save();				
}
catch (Exception $ex) {
	echo $ex->getMessage();
}
 
unset($product);

And for the very end, the actual process of going trough “One Page Checkout” under the hood. Here is the sample code.

$storeId = Mage::app()->getStore()->getId();
 
$checkout = Mage::getSingleton('checkout/type_onepage');
 
$checkout->initCheckout();
 
$checkout->saveCheckoutMethod('register');
 
$checkout->saveShippingMethod('flatrate_flatrate');
 
$checkout->savePayment(array('method'=>'checkmo'));
 
try {
	$checkout->saveOrder();
}
catch (Exception $ex) {
	//echo $ex->getMessage();
}			
 
/* Clear the cart */
$cart->truncate();
$cart->save();
$cart->getItems()->clear()->save();		
 
/* Logout the customer you created */
Mage::getSingleton('customer/session')->logout();

And thats it. This code was tested on Magento 1.3 version, but I see no reason why it would not work on latest (as of time of this writing) 1.4.0.1 version.

In any case, you hope you find it useful. As always, word of advice, this is just for testing/education purpose so please do not blindly embed it on live sites.

Cheers.

Interested in hiring us?

Have a chat with us. You would be surprised how small changes can make your business even more successful.


17 comments

  1. Hi,

    I’m having a job that login in magento from drupal.
    But it run in the second times not the first time.
    How can I fix this?

    p/s: sorry for my bad English

  2. Hi,

    In magneto checkout as guest while entering address i want to set default city that is Uneditable format. what should i need to do.?

  3. For you help
    i have find the solution for update

    ….
    ….
    …..
    try {
    $customAddress->save();
    // Check the id for update
    $id_insert = $customAddress->getId();
    }
    catch (Exception $ex) {
    //Zend_Debug::dump($ex->getMessage());
    }
    Mage::getSingleton(‘checkout/session’)->getQuote()->setBillingAddress(Mage::getSingleton(‘sales/quote_address’)->importCustomerAddress($customAddress));

    // For update
    $_custom_address2 = array (
    ‘firstname’ => ‘TEST UPDATE’,
    ‘lastname’ => ‘Ajzele’,
    ‘street’ => array (
    ‘0’ => ‘Sample address part1′,
    ‘1’ => ‘Sample address part2′,
    ),
    ‘city’ => ‘Osijek’,
    ‘region_id’ => ”,
    ‘region’ => ”,
    ‘postcode’ => ‘31000’,
    ‘country_id’ => ‘HR’, /* Croatia */
    ‘telephone’ => ‘0038531555444’,
    );

    $orderBilling = Mage::getModel(‘customer/address’)->load($id_insert);
    $orderBilling->addData($_custom_address2);
    $orderBilling->save();
    Mage::getSingleton(‘checkout/session’)->getQuote()->setBillingAddress(Mage::getSingleton(‘sales/quote_address’)->importCustomerAddress($orderBilling));

  4. Hello,

    I try to update information of billing adress
    but impossible i have this error

    string(313) “SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`magento_db`.`customer_address_entity`, CONSTRAINT `FK_CUSTOMER_ADDRESS_CUSTOMER_ID` FOREIGN KEY (`parent_id`) REFERENCES `customer_entity` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCAD)”

    Help please

  5. Hi,
    do you know how to edit and save the default billing address instead of creating a new one? I trying to implement this on one step checkout, because I need to have only one billing address for each user.

    thank you

  6. How could I set the valoue of ‘account created on’ and ‘account created in’ field ?

  7. Hi Branco,

    Great article though. I have a question, how can I update an existing customer information?

    Thanks.

  8. I had two issues:
    1) The loginById($customer->getId()) seems to work and the isLoggedIn returns true, but in the admin panel and in the shop the user is still offline.
    2) When i add a new product to the cart using the id, i get the error ‘The product could not be found.’ The id is correct… when i echo the properties of the product it’s the right product…

    Can someone help me? Thx…

  9. I’m trying to accomplish this through a small PHP script, not within mage, and it looks like it’s an hell of a mess to handle all mage tables.

    In particulare I noted that an hash is created in the customer_entity_varchar table and I don’t find the code that creates that:

    INSERT INTO `mag_customer_entity_varchar` (`entity_type_id`,`entity_id`,`attribute_id`,`value`) VALUES
    (‘1′, ‘3’, ’12’, ‘3ab1f47700301c521e3388e51f1e4c9b:8W’)

    Any idea?

  10. hi, Great Article, when we creating Customer programmatically, i need to send email confirmation also.

    How can do this?

    Thank you

  11. I’ve tried this and other similar tutorials, but no matter what I do, It keeps giving me an error, saying that there was a credit card mismatch.

    I’m using Magento 1.6.1 and the payment method is authorizenet in test mode.

  12. Hey dude,

    Nice tutorial.
    But with Magento 1.6 it was not working (at least not in first run. Once custoemr was created, in secodn run, it worked for me)

    Solution for me was also setting Shipping Address. Dunno why, but htne it worked also with newly registered users
    Mage::getSingleton(‘checkout/session’)->getQuote()
    ->setBillingAddress(Mage::getSingleton(‘sales/quote_address’)->importCustomerAddress($customAddress)) ->setShippingAddress(Mage::getSingleton(‘sales/quote_address’)->importCustomerAddress($customAddress));

  13. Tried your example but i get this ” There is already a customer registered using this email address. Please login using this email address or enter a different email address to register your account.”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.