How to add the CC’s last 4-digits to the Order Details Table (WooCommerce Stripe Payment Gateway)

Before jumping to the technical part, it’s important to note that while the Stripe for WooCommerce plugin stores card details like brand and last 4 digits for customers who save their payment methods, there might be legal considerations for customers who didn’t opt-in for having these details saved. So please use this guide as a technical reference only.

We’ll achieve this by using the get_payment_method method, which sends a GET request to the Stripe API. But before that, we’ll run some conditional logic to retrieve the Payment method ID, so we can pass it as a parameter. Additionally, we’ll use the woocommerce_pre_payment_complete hook to trigger the request, then save the details we get from the Stripe API as order metadata.

Let’s dive into the code:

Part 1: Creating the Function and Passing the Order ID

Since we’ll be using the woocommerce_pre_payment_complete hook, we can get access to the $order object by passing the order ID:

PHP
function add_card_details_to_order_meta($order_id) {
	
	$order = wc_get_order( $order_id ); 

}

Part 2: Checking Payment Method Used

To ensure this code runs only for customers paying with Stripe via a card, we’ll halt execution if the order isn’t paid with Stripe, specifically via card payment. The code below checks if the “New checkout experience is enabled” and compares the payment method title of the order with the one set in the plugin settings. We can simplify this by directly comparing get_payment_method_title to the payment method title but I’m going this route because I know most people want to copy and paste the snippet directly to their functions.php file. 🙂

PHP

	if ($order->get_payment_method() === 'stripe') {
		$UPE = new WC_Stripe_UPE_Payment_Gateway();
		$default = new WC_Gateway_Stripe();

		$payment_method_title = strval(WC_Stripe_Feature_Flags::is_upe_checkout_enabled() ? $UPE->get_title() : $default->get_title());

		if ($order->get_payment_method_title() !== $payment_method_title) {
			return;
		}
		}

Part 3: Searching for Stripe Source ID or Payment Method ID

PHP
$found = '';

// Looping through the order meta to check for the Stripe source ID or Payment method ID.

foreach ($order->get_meta_data() as $object) {
	$object_array = array_values((array)$object);
	foreach ($object_array as $object_item) {
		if ($object_item['key'] == '_stripe_source_id' || $object_item['key'] == '_payment_method_id') {
			$found = $object_item['value'];
			break; 
		}
	}
}

Part 4: Retrieving Card Details and Storing Them

In the final step (assuming we have found one of the values) we will pass it to the get_payment_method function to get all the payment details from Stripe, we’ll only store the things we need, in this case, the Card brand and last 4 digits.

PHP
if ( !$order->meta_exists('_card_brand')) {
	$data_dump = WC_Stripe_API::get_payment_method($found);
	$cardBrand = $data_dump->card->brand;
    $last4digits = $data_dump->card->last4;
	$order->add_meta_data('_card_brand', $cardBrand);
	$order->add_meta_data('_card_last_4', $last4digits);
	$order->save();
}

Piecing everything together:

PHP
function add_card_details_to_order_meta($order_id) {

  // prevent fatal errors if the plugin is not activated.
 if ( !is_plugin_active('woocommerce-gateway-stripe/woocommerce-gateway-stripe.php') ) {
  return;
  }
	
	$order = wc_get_order($order_id);

	if ($order->get_payment_method() === 'stripe') {
		$UPE = new WC_Stripe_UPE_Payment_Gateway();
		$default = new WC_Gateway_Stripe();

		$payment_method_title = strval(WC_Stripe_Feature_Flags::is_upe_checkout_enabled() ? $UPE->get_title() : $default->get_title());

		if ($order->get_payment_method_title() !== $payment_method_title) {
			return;
		}

	$found = '';

// Looping throught the order meta to check for the Stripe source ID or Payment method ID.

	foreach ($order->get_meta_data() as $object) {
		$object_array = array_values((array)$object);
		foreach ($object_array as $object_item) {
			if ($object_item['key'] == '_stripe_source_id' || $object_item['key'] == '_payment_method_id') {
				$found = $object_item['value'];
				break; 
			}
		}
	}


// Check if data that we'll be adding already exist in the order, if not, lets add the card brand and last 4 digits from the $data_dump.

	if ( !$order->meta_exists('_card_brand')) {
		$data_dump = WC_Stripe_API::get_payment_method($found);
		$cardBrand = $data_dump->card->brand;
	    $last4digits = $data_dump->card->last4;
		$order->add_meta_data('_card_brand', $cardBrand);
		$order->add_meta_data('_card_last_4', $last4digits);
		$order->save();
	}
}

}

add_action('woocommerce_pre_payment_complete', 'add_card_details_to_order_meta');

If you’re wondering where to add this, just install the ‘Code Snippets‘ plugin, create a new snippet, paste the code and give it a title.



Now that we’ve successfully gathered and stored the card brand and last four digits, the next step is to display this in the order details table, order emails, or wherever you prefer. As an example, let’s add these details to the order details section on the “Order Received” page and the “My Account” page.

PHP
function display_custom_order_meta($order){
    // Get the custom meta data you want to display
    $card_brand = $order->get_meta('_card_brand');
    $card_last_4 = $order->get_meta('_card_last_4');

    // Check if the meta data exists before displaying it
	if ($card_brand && $card_last_4) {
		?>
			<tr>
				<th scope="row">Paid with:</th>
                <td><?php echo esc_html(ucfirst($card_brand) . " " . $card_last_4); ?></td>
			</tr>
		<?php
		} }
		

add_action('woocommerce_order_details_after_order_table_items', 'display_custom_order_meta');

End result:

And that’s it, I hope this helps in what you’re trying to achieve, if you have any questions you can comment them below. :‎)

Need help building a custom WooCommerce/WordPress solution? Feel free to submit the contact form here for a quote.


Comments

4 responses to “How to add the CC’s last 4-digits to the Order Details Table (WooCommerce Stripe Payment Gateway)”

  1. This code snippet does not seem to work on plugin Woocommerce Stripe Gateway ver. 7.9.1
    Does it need an update?

    1. Hello Victor,

      Everything seems to be working fine from my end. Here’s a screenshot for reference: http://i.imgur.com/TLqVvC2.png

      I recommend checking if the data is stored in the order meta. If navigating through the database seems complex, you can simply go to WooCommerce -> Settings -> Features -> Order storage and opt for the post table. Then, install this plugin: https://wordpress.org/plugins/jsm-show-post-meta/

      Now, when you navigate to the order page, and you should find all the related post meta at the bottom. If _card_brand and _card_last_4 are registered, the issue is most likely just with displaying the values, possibly due to a theme/plugin conflict. To pinpoint the issue, I suggest performing a full conflict test as explained here: https://woo.com/document/how-to-test-for-conflicts/

      Let me know if you have any other questions!

  2. Victor Avatar
    Victor

    If the payment is by Apple Pay or Google Pay through Stripe’s gateway, would this still work?

    1. No, it won’t work. The code specifically looks for the default payment method title (which is used for card payments) and compares it with the title from the $order object before calling the Stripe API.

      You could modify Part 2 to include Apple/Google Pay, but I haven’t had a chance to review that part of the Stripe plugin codebase yet.

      Additionally, with Apple Pay, there may be two sets of last 4 digit values in the card object: one for the actual card (default value) and another for the Apple Pay generated one (dynamic_last4), so depending on which one you’d like to show, you might need to edit more things.

      If you’d like to get a quote for building a custom solution, feel free to contact me from here or on Upwork. : )

Leave a Reply

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