Scriptbaker
SCRIPTBAKERAI & Software Engineering
Magento

Magento Order Using Saved Credit Card

Creating order is the basic functionality of Magento but its the trickiest one at the same time for developers. Yes, its true because its not straight forward l

· 5 min read · By Tahir Yasin

Creating an order programmatically is one of the more complex tasks in Magento 1 because an order is not created by simply loading a product, assigning a few values, and calling save(). Magento checkout uses several objects and steps, including the customer, quote, products, addresses, shipping method, payment method, totals, and order conversion.

This becomes particularly useful when you need to create Magento orders automatically from a cron job, subscription process, internal application, customer reorder workflow, or another backend process.

Magento's quote is an important part of this process. It holds the products, customer information, addresses, shipping information, payment method, and calculated totals before the quote is converted into an order. This is why the normal programmatic order flow usually starts by creating and configuring a quote before submitting it as an order.

What You Need Before Creating a Magento Order

Before running a custom order creation script, make sure you have the following information available:

  • Magento store ID
  • Customer ID or customer email address
  • Product ID and quantity
  • Billing address
  • Shipping address, when the order is not virtual
  • Valid shipping method
  • Valid payment method
  • Saved payment token or card identifier when using a stored credit card

The exact payment and saved-card implementation depends on the Magento payment extension installed on the website. A stored-card token should not be treated as the actual credit card number. Tokenization allows payment systems to reference a saved payment method without your Magento application storing the customer's raw card details.

How Magento Creates an Order Programmatically

The general process can be broken into the following steps:

  1. Load the Magento store.
  2. Load the customer.
  3. Create a sales quote.
  4. Assign the customer to the quote.
  5. Add one or more products to the quote.
  6. Add billing and shipping addresses.
  7. Set the shipping method.
  8. Set the payment method.
  9. Import any required payment data.
  10. Collect quote totals.
  11. Convert the quote into an order.
  12. Place and save the order.
  13. Deactivate the quote after successful order creation.

This quote-based approach is important because Magento needs the quote to calculate shipping, taxes, discounts, and the final order total before the order is submitted. Modern Adobe Commerce documentation follows the same general concept of using a quote to hold cart, address, shipping, payment, and totals information before order placement.

Basic Magento Programmatic Order Example

Below is a working Magento 1 example that creates an order using the Bank Transfer payment method and Flat Rate shipping method. You can replace these methods with the payment and shipping methods configured on your Magento installation.

$store_id = '1'; // replace if you are running script from frontend Mage::app()->getStore()->getId()
$customer_id = 'INSERT_CUSTOMER_ID_HERE'; // Mage::getSingleton('customer/session')->getId(); for current logged in user from frontend
/*------------------------------------------------------------------------
Payment and Shipping Method
------------------------------------------------------------------------*/
$payment_method = 'banktransfer';
$shipping_method = 'flatrate_flatrate';
/*------------------------------------------------------------------------
Load Customer
------------------------------------------------------------------------*/
$customer = Mage::getModel('customer/customer');
$customer->setWebsiteId($store_id);
$customer->loadByEmail($customer_id);
/*------------------------------------------------------------------------
Create a Quote
------------------------------------------------------------------------*/
$quote = Mage::getModel('sales/quote');
$quote->setStoreId($store_id);
$quote->assignCustomer($customer);
$quote->setSendCconfirmation(1);
/*------------------------------------------------------------------------
Add products to Quote
------------------------------------------------------------------------*/
$product = Mage::getModel('catalog/product')->load(554);
$quote->addProduct(
    $product,
    new Varien_Object(
        array(
            'qty' => 1
        )
    )
);
/*------------------------------------------------------------------------
Assign Address, Shipping and Payment methods
------------------------------------------------------------------------*/
$address_data = array(
    'firstname' => 'Tahir',
    'lastname' => 'Yasin',
    'street' => array(
        '0' => 'Sample Street'
    ),
    'city' => 'Sample City',
    'postcode' => '01234',
    'telephone' => '0123456789',
    'country_id' => 'MY',
    'region_id' => NULL,
);
$billingAddress = $quote->getBillingAddress()->addData($address_data);
$shippingAddress = $quote->getShippingAddress()->addData($address_data);
$shippingAddress
    ->setCollectShippingRates(true)
    ->collectShippingRates()
    ->setShippingMethod($shipping_method)
    ->setPaymentMethod($payment_method);
$quote->getPayment()->importData(
    array(
        'method' => $payment_method
    )
);
$quote->collectTotals()->save();
/*----------------------------------------------------------------------*/
/*------------------------------------------------------------------------
SECTION : CHECKOUT
------------------------------------------------------------------------*/
$convertQuote = Mage::getModel('sales/convert_quote');
if ($quote->getIsVirtual()) {
    $order = $convertQuote->addressToOrder(
        $quote->getBillingAddress()
    );
} else {
    $order = $convertQuote->addressToOrder(
        $quote->getShippingAddress()
    );
}
// assign payment method
$quotePayment = $quote->getPayment();
$quotePayment->setMethod(
    $quote->getPayment()->getMethod()
);
$quote->setPayment($quotePayment);
$orderPayment = $convertQuote->paymentToOrderPayment($quotePayment);
$order->setBillingAddress(
    $convertQuote->addressToOrderAddress(
        $quote->getBillingAddress()
    )
);
$order->setPayment(
    $convertQuote->paymentToOrderPayment(
        $quote->getPayment()
    )
);
if (!$quote->getIsVirtual()) {
    $order->setShippingAddress(
        $convertQuote->addressToOrderAddress(
            $quote->getShippingAddress()
        )
    );
}
// set payment options
$order->setPayment(
    $convertQuote->paymentToOrderPayment(
        $quote->getPayment()
    )
);
// order products
$items = $quote->getAllItems();
foreach ($items as $item) {
    //@var $item Mage_Sales_Model_Quote_Item
    $orderItem = $convertQuote->itemToOrderItem($item);
    if ($item->getParentItem()) {
        $orderItem->setParentItem(
            $order->getItemByQuoteItemId(
                $item->getParentItem()->getId()
            )
        );
    }
    $order->addItem($orderItem);
}
$order->setCanShipPartiallyItem(false);
$order->sendNewOrderEmail();
$order->place();
$order->save();
$quote->setIsActive(0);
$quote->save();

Using a Saved Credit Card to Create the Magento Order

If you are using an Authorize.net CIM module that supports stored cards, the process is slightly different. Instead of submitting the customer's full credit card information, the payment method can receive the identifier of a previously saved card.

Stored-card systems generally use tokenization so that the merchant application can reference a saved payment method without keeping the customer's raw card number in Magento. Authorize.net's CIM functionality supports charging stored customer payment profiles, while Magento payment extensions can provide their own integration layer for saved-card tokens.

If you are using the Authorize.net CIM implementation referenced by the original script, change the payment method to authnetcim and pass the saved card identifier to importData().

Here is the original saved-card portion of the implementation:

$savedCards = Mage::getModel('tokenbase/card')->getCollection();
$savedCards->addFieldToFilter('active', 1)
    ->addFieldToFilter('customer_id', $customer_id);
$card = $savedCards->getFirstItem();
$quote->getPayment()->importData(
    array(
        'method' => $payment_method,
        'card_id' => $card->getHash(),
    )
);

The important part is that the saved card belongs to the customer whose quote is being processed. Your payment extension may use a different model, token field, or payment-data parameter, so do not assume that tokenbase/card or card_id will work with every Authorize.net extension.

Complete Saved Credit Card Flow

For an automated Magento order using a previously saved card, the process can be summarized as follows:

  1. Identify the customer.
  2. Load an active saved payment method belonging to that customer.
  3. Create a quote for the customer.
  4. Add the required product or products.
  5. Set billing and shipping addresses.
  6. Set the appropriate shipping method.
  7. Set the Authorize.net CIM payment method.
  8. Pass the saved-card token or identifier to the payment extension.
  9. Collect quote totals.
  10. Convert the quote to an order.
  11. Submit the order through the payment method's normal processing flow.
  12. Log the resulting order and payment response for troubleshooting.

Why collectTotals() Is Important

One of the most commonly missed steps when creating Magento orders programmatically is collecting quote totals.

The quote may need to calculate product prices, discounts, taxes, shipping costs, and the final grand total. Magento's quote system uses these calculations before an order is submitted. If totals are not collected at the appropriate stage, you can encounter incorrect totals, unavailable payment methods, missing shipping charges, or order-placement errors.

$quote->collectTotals()->save();

For this reason, collectTotals() should be treated as an important part of a custom Magento 1 order workflow rather than an optional cleanup step.

Choosing the Correct Payment Method Code

The payment method code used in PHP is not necessarily the same as the payment method's display name in the Magento Admin.

For example, a payment method may appear to customers as "Bank Transfer" while its internal code is banktransfer. Likewise, a third-party Authorize.net CIM extension may use an internal code such as authnetcim.

Always verify the actual method code used by your installed extension before using it in a custom script.

Choosing the Correct Shipping Method

The same principle applies to shipping methods.

For example:

$shipping_method = 'flatrate_flatrate';

This represents the internal carrier and method code rather than the human-readable name displayed during checkout.

If the shipping method is unavailable for the customer's country, postcode, cart contents, or store configuration, the quote may fail to calculate the expected shipping rate.

How to Find a Customer Before Creating the Order

Your script needs to associate the quote with the correct customer. In an automated process, this might come from a customer ID or email address.

For example:

$customer = Mage::getModel('customer/customer');$customer->setWebsiteId($store_id);$customer->loadByEmail($customer_email);

When creating orders for existing customers, validate that the customer was actually found before continuing. This prevents an automated job from creating an incomplete quote or failing later in the checkout process.

Validating the Saved Card Before Charging

A saved-card query should not simply select the first record and assume that it can be charged.

The original example uses:

$savedCards->addFieldToFilter('active', 1)    ->addFieldToFilter('customer_id', $customer_id);

For a production implementation, you should additionally consider what your payment extension defines as a usable card. For example, a card could have been deleted, disabled, expired, or otherwise become unavailable depending on the extension and gateway integration.

You should also handle the case where the customer has no active saved card rather than passing an empty card identifier to the payment method.

Example: Check Whether a Saved Card Exists

$savedCards = Mage::getModel('tokenbase/card')->getCollection();
$savedCards->addFieldToFilter('active', 1)
    ->addFieldToFilter('customer_id', $customer_id);
$card = $savedCards->getFirstItem();
if (!$card->getId()) {
    Mage::throwException(
        'No active saved credit card was found for this customer.'
    );
}

This type of validation is especially useful for cron jobs and recurring processes because it allows the application to fail gracefully instead of attempting to process an invalid payment.

Using Magento Cron to Create Orders Automatically

Programmatic order creation is commonly used with Magento cron jobs. For example, a scheduled process might create an order for a subscription, recurring service, replenishment workflow, or another business process.

When running this code through cron, make sure the Magento application is initialized correctly before using Magento models.

require_once 'app/Mage.php';
Mage::app('admin');
try {
    // Your order creation logic here.
} catch (Exception $e) {
    Mage::log(
        $e->getMessage(),
        Zend_Log::ERR,
        'automatic-order.log',
        true
    );
}

The exact application initialization can vary depending on where your script lives and how your Magento installation is configured.

Handling Payment Failures

Creating an order and successfully charging a saved credit card are related but separate concerns. A payment gateway can reject a transaction even when the Magento quote itself is valid.

For production automation, wrap the payment and order process in exception handling and log enough information to identify the failed customer, quote, order, and gateway response without recording sensitive card information.

try {
    // Create quote
    // Add products
    // Add addresses
    // Set shipping
    // Set saved payment method
    // Collect totals
    // Place order
} catch (Mage_Core_Exception $e) {
    Mage::log(
        $e->getMessage(),
        Zend_Log::ERR,
        'order-creation.log',
        true
    );
} catch (Exception $e) {
    Mage::log(
        $e->getMessage(),
        Zend_Log::ERR,
        'order-creation.log',
        true
    );
}

Do Not Store Raw Credit Card Details

When implementing saved-credit-card functionality, do not modify the script to store full credit card numbers, CVV codes, or other sensitive authentication data in Magento database tables or log files.

A tokenized payment integration is designed to allow the application to reference a stored payment method without handling the raw card number during every transaction. Authorize.net's CIM documentation describes stored customer payment profiles that can be used for subsequent transactions.

Your Magento extension and gateway configuration should determine how payment tokens are created, stored, and submitted. Never assume that a database value containing card-related information is safe to expose in logs or custom application code.

Common Problems When Creating Magento Orders Programmatically

1. Payment Method Is Not Available

This can happen when the payment method code is incorrect, the method is disabled, the customer or shipping country is not supported, or the quote does not meet the payment method's configured conditions.

2. Shipping Method Is Not Available

Verify the carrier code, method code, destination country, postcode, product configuration, and shipping configuration.

3. Quote Total Is Incorrect

Make sure products, customer information, addresses, shipping methods, discounts, and taxes are configured before calling collectTotals().

4. Saved Card Is Not Found

Check that the saved card belongs to the same customer assigned to the quote and that your payment extension marks the card as active and usable.

5. Payment Gateway Rejects the Transaction

A valid Magento quote does not guarantee a successful payment. Gateway responses, fraud rules, AVS/CVV checks, account configuration, expired cards, and other payment-provider rules can affect the transaction.

6. Duplicate Orders Are Created

This is particularly important when using cron jobs. If a scheduled process is retried after a timeout, it should not blindly create another order. Consider storing an external transaction ID or internal process ID and checking whether the operation has already been completed.

Preventing Duplicate Automated Orders

If your script runs automatically, use an idempotent workflow where possible. Before creating a new order, determine whether the same business event has already generated an order.

For example, if an external subscription ID is responsible for creating an order, store that ID with the resulting Magento order and check it before retrying.

// Example concept only:
//
// 1. Receive subscription/event ID.
// 2. Search for an existing Magento order using that ID.
// 3. If an order already exists, stop.
// 4. Otherwise create the quote and order.
// 5. Store the external reference against the order.

This is especially important for payment-related automation because a timeout does not necessarily mean that the gateway did not process the transaction.

Magento 1 Compatibility Considerations

The code in this article uses Magento 1 classes such as Mage::getModel(), sales/quote, and sales/convert_quote. These APIs belong to the Magento 1 architecture and should not be copied directly into Magento 2 code.

If you are maintaining an older Magento 1 store, test custom order automation in a staging environment before deploying it to production. Third-party payment modules can also change the expected payment data structure, so the exact implementation should be verified against the extension installed on your store.

Testing the Magento Saved Card Order Process

Before enabling automatic order creation, test the complete flow using a non-production payment environment whenever your gateway and extension provide one.

Verify each of the following:

  • The correct customer is loaded.
  • The expected product and quantity are added.
  • Billing and shipping addresses are correct.
  • The shipping rate is calculated correctly.
  • The correct payment method is selected.
  • The saved-card token belongs to the correct customer.
  • The quote grand total matches the expected amount.
  • The gateway response is handled correctly.
  • The Magento order is created only once.
  • The order status and invoice state are correct.
  • Failure responses are logged without sensitive payment information.

Magento Order Using Saved Credit Card: Key Takeaways

Creating a Magento order programmatically requires more than saving an order model. The quote needs to be correctly configured with the customer, products, addresses, shipping method, payment method, and calculated totals before it is converted into an order.

When a saved credit card is involved, the payment extension becomes particularly important. The extension must support tokenized stored cards and define how the saved payment identifier is passed to the payment method.

For the Authorize.net CIM example in this article, the saved card is retrieved from the customer's active tokenized cards and its hash is passed through the payment data:

$quote->getPayment()->importData(    array(        'method' => $payment_method,        'card_id' => $card->getHash(),    ));

Always verify this against the specific payment extension installed on your Magento store because different extensions can use different models and parameters.

Frequently Asked Questions

Can Magento create an order programmatically?

Yes. Magento 1 can create orders programmatically by building and configuring a sales quote and then converting that quote into an order. The quote should contain the customer, products, addresses, shipping method, payment method, and calculated totals before order submission.

How do I create a Magento order automatically?

Create a quote, assign the customer, add products, configure billing and shipping addresses, select the shipping and payment methods, collect totals, and then submit the quote as an order. For recurring or scheduled workflows, this process can be executed from a Magento cron job.

Can I create a Magento order using a saved credit card?

Yes, if the installed payment extension supports tokenized saved cards and exposes a way to identify the stored payment method. The exact implementation depends on the payment extension. In the Authorize.net CIM example above, the saved card identifier is passed through the quote payment data.

Does Magento store the customer's full credit card number?

A properly implemented tokenized payment integration should use a payment token or customer payment profile instead of storing the raw card number in the Magento application. The exact storage and processing behavior depends on the payment gateway and extension.

What is the purpose of Magento's sales quote?

A Magento quote represents the customer's cart before it becomes an order. It can contain products, customer information, addresses, shipping information, payment information, and calculated totals. Magento uses the quote as an important part of the checkout-to-order process.

Why do I need to call collectTotals()?

collectTotals() recalculates the quote totals after products, addresses, shipping, discounts, taxes, and other relevant information have been configured. Without the appropriate totals calculation, an automated checkout can produce incorrect totals or fail during order processing.

Why is my saved credit card not found?

Check that the customer ID is correct, the saved card belongs to that customer, the card is active, and the payment extension's token model and fields match your implementation. Also verify that the payment method is enabled and configured correctly.

Can I use this code with every Magento payment gateway?

No. The basic quote-to-order workflow is reusable, but payment integrations can require different payment data and processing logic. A third-party payment extension may use a different payment method code, token model, or saved-card parameter.

Can this Magento script be used with cron?

Yes. Programmatic order creation is suitable for scheduled workflows, but production cron jobs should include error handling, duplicate-order protection, logging, and appropriate payment-gateway handling.

How can I avoid duplicate orders in an automated Magento process?

Use a unique business or external transaction reference and check whether an order has already been created before starting another payment attempt. This is especially important when a cron job or external system retries a request after a timeout.

Is this code for Magento 1 or Magento 2?

This implementation is for Magento 1 because it uses Magento 1 classes such as Mage::getModel(). Magento 2 uses a different service-contract, dependency-injection, quote, and order-management architecture.

Conclusion

Creating a Magento order using a saved credit card requires a properly configured quote and a payment extension that supports tokenized payment methods. The safest approach is to let the payment gateway and its Magento extension handle the sensitive payment information while your application works with the supported payment token or stored-card identifier.

The example in this guide demonstrates the core Magento 1 workflow: create a quote, assign the customer, add products, configure addresses and shipping, select the payment method, provide the saved-card identifier, collect totals, and convert the quote into an order.

Because Magento 1 payment extensions can implement saved cards differently, always test the complete workflow in a staging environment and verify the implementation against the exact extension and gateway configuration used by your store.

Last updated:

Work with Scriptbaker

Let's talk about your project

Whether you're extending an existing platform, modernising legacy code, or planning something new, our engineers can help. Tell us what you're working on and we'll explore a practical technical solution together.