Stripe Checkout payment gateway

Implements a payment gateway for Stripe Checkout Sessions. Works in both checkout place-order flow and my account order-pay flow.

This example sets the payment method type to `us_bank_account` (eCheck for payments or ACH for subscriptions) and you can customize this accordingly.

With this implementation you must manually map WooCommerce product ID and Qty to Stripe price IDs in the settings panel.

Must be set to run on both front-end and back-end (everywhere).

add_action( 'woocommerce_init', function() {

	// Payment Gateway Class
	class WC_Gateway_StripeCheckout extends WC_Payment_Gateway {

		// Constructor
		function __construct() {
			$this->endpoint = 'https://api.stripe.com/v1';
			$this->has_fields = false;
			$this->id = 'stripecheckout';
			$this->method_title = 'Stripe Checkout';
			$this->method_description = 'Implements Stripe Checkout Session';
			$this->init_form_fields();
			$this->init_settings();
			$this->title = $this->get_option( 'title' );
			add_action(
				'woocommerce_update_options_payment_gateways_' . $this->id,
				[ $this, 'process_admin_options' ]
			);
		}

		// Settings Fields
		function init_form_fields() {
			$this->form_fields = array(
				'enabled' => array(
					'title' => __( 'Enable/Disable', 'woocommerce' ),
					'type' => 'checkbox',
					'label' => 'Enable Stripe Checkout',
					'default' => 'yes',
				),
				'testmode' => array(
					'title' => __( 'Test mode', 'woocommerce' ),
					'type' => 'checkbox',
					'label' => 'Enable test mode',
					'default' => 'yes',
				),
				'title' => array(
					'title' => __( 'Title', 'woocommerce' ),
					'type' => 'text',
				),
				'sec_key_live' => array(
					'title' => 'Secret key (live)',
					'type' => 'text',
				),
				'sec_key_test' => array(
					'title' => 'Secret key (test)',
					'type' => 'text',
				),
				'prices' => array(
					'title' => 'Price ID CSV',
					'type' => 'textarea',
					'description' => 'Per line: product id,quantity,stripe price id',
				),
			);
		}

		// WooCommerce Order Submitted
		function process_payment( $order_id ) {

			// Get Customer And Order
			$customer = WC()->session->get( 'customer' );
			$order = wc_get_order( $order_id );

			// Set Payent Pending Status
			$order->update_status(
				'pending', __( 'Awaiting payment', 'woocommerce' )
			);

			// Assemble Stripe Price ID Line Items
			$line_items = [];
			$prices = explode( PHP_EOL, $this->settings['prices'] );
			foreach( $order->get_items() as $order_item ) {
				$product_id = isset( $order_item['product_id'] )
					? $order_item['product_id'] : 0;
				$quantity = isset( $order_item['quantity'] )
					? $order_item['quantity'] : 0;
				$items = preg_grep(
					"/{$product_id},{$quantity},/i", $prices
				);
				foreach( $items as $item ) {
					list( $product_id, $quantity, $stripe_price_id )
						= explode( ',', $item );
					$line_items[] = [
						'price' => trim( $stripe_price_id ),
						'quantity' => 1,
					];
				}
			}

			// Handle No Line Items
			if( ! $line_items ) {
				$message = sprintf(
					'Unable to match your cart item(s) and quantity to Stripe.'
				);
				$order->update_status( 'failed', $message );
				wc_add_notice( $message, 'error' );
				return;
			}

			// Handle Test Mode
			$sec_key = $this->settings['testmode'] == 'yes'
				? $this->settings['sec_key_test']
				: $this->settings['sec_key_live'];

			// Build Request
			$args = [
				'headers' => [
					'Authorization' => sprintf(
						'Basic %s',
						base64_encode( $sec_key . ':' )
					),
				],
				'body' => [
					'payment_method_types' => [
						'us_bank_account',
					],
					'line_items' => $line_items,
					'mode' => 'payment',
					'success_url' => $this->get_return_url( $order )
						. '&stripe_session_id={CHECKOUT_SESSION_ID}',
					'cancel_url' => $order->get_checkout_payment_url(),
				],
			];

			// Maybe Attach Customer
			$stripe_customer_id = get_user_meta(
				get_current_user_id(), '_stripe_customer_id', true
			);
			if( $stripe_customer_id ) {
				$args['body']['customer'] = $stripe_customer_id;
			}

			// Send Checkout Session Request
			$url = $this->endpoint . '/checkout/sessions';
			$result = wp_remote_post( $url, $args );
			$result = wp_remote_retrieve_body( $result );
			$result = json_decode( $result );

			// Handle Checkout Session Error
			if( empty( $result->url ) ) {
				$message = sprintf(
					'Problem with Stripe Checkout: %s',
					isset( $result->error->message )
						? $result->error->message : ''
				);
				$order->update_status( 'failed', $message );
				wc_add_notice( $message, 'error' );
				return;
			}

			// Handle Checkout Redirect
			$order->add_order_note( 'Redirected to Stripe Checkout' );
			return [
				'result' => 'success',
				'redirect' => $result->url
			];

		} // End Process Payment Function

	} // End Payment Class

} ); // End Woo Init Hook

// Add Gateway To WooCommerce
add_filter( 'woocommerce_payment_gateways', function( $methods ) {

	$methods[] = 'WC_Gateway_StripeCheckout'; 
	return $methods;

} );

// Handle Successful Payments
add_action( 'woocommerce_thankyou_stripecheckout', function( $order_id ) {

	// Get Order
	$order = wc_get_order( $order_id );
	if( is_wp_error( $order ) || ! $order ) {
		return;
	}

	// Order Key Verification
	$order_key = isset( $_GET['key'] )
		? esc_attr( $_GET['key'] ) : '';
	if( $order_key != $order->get_order_key() ) {
		return;
	}

	// Session ID Check
	$stripe_session_id = isset( $_GET['stripe_session_id'] )
		? esc_attr( $_GET['stripe_session_id'] ) : '';

	// Update Order Status
	if( $order->get_total() > 0 ) {
		$order->update_status(
			'on-hold',
			'Awaiting eCheck to clear; usually up to four business days.'
		);
	} else {
		$order->payment_complete();
	}

	// Empty The Cart
	if( isset( WC()->cart ) ) {
		WC()->cart->empty_cart();
	}

	// Add Order Note
	$order->add_order_note(
		'Stripe Checkout success ' . $stripe_session_id
	);

} );
  1. Log into a staging, development, or locally hosted clone of your site.
  2. Install and activate the Code Snippets plugin.
  3. Navigate to WP Admin > Snippets > Add New.
  4. Copy and paste the code from the Description tab above.
  5. Check to ensure formatting came over properly and no syntax errors show up in the editor.
  6. Customize the code as desired.
  7. Add a meaningful title and description.
  8. Select whether to run on front-end or back-end (or both). Some snippets require both.
  9. Click the “Save and Activate” button.
  10. Test your site to ensure it works as expected.
  11. Disable if any problems, or recover as necessary.
  12. Repeat steps two onward on your live environment.
  1. Describe the issue and what you’ve observed.
  2. Describe your expected outcome(s).
  3. List steps to reproduce the issue.
  4. Optionally provide screen-shot or video URLs.

[ccom_contact_form]

We code all of our code snippets directly. Our clients provide most of the ideas and demand for the functionality provided by our code snippets.

There are several sources one can find on Google for code that has inspired or contributed to this open-source library. Here’s some main ones:

All code snippets are licensed GPLv2 (or later) matching WordPress licensing.

Disclaimer of warranty:

Except when otherwise stated in writing the copyright holders and/or other parties provide the program as-is without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose.