Authorize by Product
Some products require different payment handling than others. Maybe you sell both physical items that ship immediately and custom products that take weeks to manufacture. Or perhaps you offer pre-orders alongside regular inventory. In these scenarios, you might want to authorize payments for certain products while allowing immediate capture for others.
This approach gives you the flexibility to hold funds for specific products without affecting your entire payment flow. When a customer's cart contains a product that requires authorization, the payment will be authorized but not captured, giving you time to fulfill the order before collecting the funds.
When would you use this?
Authorization by product is particularly useful for merchants who sell a mix of product types that require different fulfillment timelines. Instead of authorizing all payments or none at all, you can make intelligent decisions based on what's actually in the customer's cart.
Common use cases include separating pre-orders from in-stock items, handling custom or made-to-order products differently from ready-to-ship inventory, or managing high-value items that require additional verification before shipment.
The Code
This example checks for a specific product (ID 14) in the customer's cart. If that product is present, the payment will be authorized instead of captured immediately. Add this code to your theme's functions.php
file or a custom plugin:
/**
* Set authorization intent when creating PayPal order from cart
* @param \PaymentPlugins\PayPalSDK\Order $order
* @param \PaymentPlugins\WooCommerce\PPCP\Factories\OrderFactory $factory
*/
add_filter('wc_ppcp_order_factory_from_cart', function($args, $factory){
foreach($factory->get_cart()->get_cart() as $cart_data){
$product = $cart_data['data'];
if($product->get_id() === 14){
$args->setIntent('authorize');
}
}
return $args;
}, 10, 2);
/**
* Set authorization intent for PayPal query parameters
* @param \PaymentPlugins\WooCommerce\PPCP\PayPalQueryParams $query_params
* @param \PaymentPlugins\WooCommerce\PPCP\ContextHandler $context
*/
add_action('wc_ppcp_paypal_query_params', function($query_params, $context){
if(WC()->cart){
foreach(WC()->cart->get_cart() as $cart_data){
$product = $cart_data['data'];
if($product->get_id() === 14){
$query_params->intent = 'authorize';
}
}
}
}, 100, 2);
How the Code Works
The code uses two hooks to ensure authorization happens at different stages of the PayPal payment process. The first hook (wc_ppcp_order_factory_from_cart
) runs when the PayPal order is being created from the cart contents. It loops through each item in the cart and checks if the product ID matches 14. When it finds a match, it sets the payment intent to "authorize" instead of the default "capture."
The second hook (wc_ppcp_paypal_query_params
) handles the PayPal query parameters and performs the same check. This ensures that both the order creation and the PayPal communication are set to use authorization when product ID 14 is present in the cart.
Customizing for Multiple Products
You can easily modify this code to check for multiple products by changing the condition:
// Check for multiple product IDs
if(in_array($product->get_id(), [14, 25, 36])){
$args->setIntent('authorize');
}
Or check based on product categories:
// Check if product belongs to a specific category
if($product->get_category_ids() && in_array(15, $product->get_category_ids())){
$args->setIntent('authorize');
}
Important Considerations
PayPal authorizations are valid for up to 29 days, after which they expire and cannot be captured. Make sure your fulfillment process can complete within this timeframe, or you'll need to process a new payment.
Testing Your Implementation
To verify the code is working correctly, add one of your specified products to a test cart and complete a purchase in your PayPal sandbox environment. Check your PayPal sandbox dashboard to confirm the payment shows as "Authorized" rather than "Completed."
Remember to change the product ID from 14 to match your actual products before deploying to your live site.