WooCommerce: Multiple Stripe Accounts (Solved)

The WooCommerce plugin fully integrates with the WooCommerce Stripe Payment Gateway plugin, developed by Automattic itself. With this free plugin, Stripe payment gateway can be enabled via the WooCommerce settings and once your Stripe “Live Publishable Key” and “Live Secret Key” are set, your WooCommerce shop is ready to take credit card payments powered by Stripe.

Now, there is some documentation online which explains, with a little bit of code, how to switch Stripe account programmatically and conditionally i.e. for a given product ID or product category slug – same as what we’ve seen recently with PayPal Standard (here’s the tutorial for using different PayPal accounts inside a single WooCommerce installation). For example, you may want to use a Stripe account for digital sales and a different one for physical products.

Unlike PayPal Standard, however, online documentation and snippets are quite out of date and require, often, to create a custom Class which is always a difficult task in PHP programming. Thankfully, there are new WooCommerce Stripe hooks and therefore it’s possible to use different / multiple Stripe accounts in a single WooCommerce installation.

Please read the disclaimer below and – only then – enjoy!

My goal is to use my Stripe keys for all payments apart from a given product ID which will need to deposit funds into a different Stripe account.

PHP Snippet: Use Different Stripe Account For a Product ID @ WooCommerce Checkout

Disclaimer: the snippet below MAY CAUSE side effects – use at your own risk. For example, it can mess with Stripe refund handling (better if you manually create refunds from Stripe as opposed to using WooCommerce order admin) or generate other unknown errors. Customizing payment gateways is very dangerous and should be done only if you are aware of the potential consequences. Please test this thoroughly.
Please note: the snippet below looks for a Product ID inside the order and switches Stripe keys if successful. In case the order contains several products you’d need to find a workaround, for example by allowing only 1 product in the Cart.
/**
 * @snippet       Switch Stripe Account @ WooCommerce Checkout
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli, BusinessBloomer.com
 * @testedwith    WooCommerce 4.6
 * @community     https://businessbloomer.com/club/
 */

// -------------------
// 1. Create function to find Product ID

function bbloomer_product_id_in_cart( $id ) {
	$product_cart_id = WC()->cart->generate_cart_id( $id );
	$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
	if ( $in_cart ) return true;
	return false;
}

// -------------------
// 2. Change Stripe keys on the go

add_filter( 'wc_stripe_params', 'bbloomer_conditional_publishable_key', 9999 );

function bbloomer_conditional_publishable_key( $params ) {

	// PRODUCT ID HERE
	if ( ! bbloomer_product_id_in_cart( 12345 ) ) return $params;

	// STRIPE Live Publishable Key HERE
	$params[ 'key' ] = 'pk_live_................';

	return $params;
}

add_filter( 'wc_stripe_payment_request_params', 'bbloomer_conditional_publishable_key_request', 9999 );

function bbloomer_conditional_publishable_key_request( $params ) {

	// PRODUCT ID HERE
	if ( ! bbloomer_product_id_in_cart( 12345 ) ) return $params;

	// STRIPE Live Publishable Key HERE
	$params[ 'stripe' ][ 'key' ] = 'pk_live_................';

	return $params;
}

add_filter( 'woocommerce_stripe_request_headers', 'bbloomer_conditional_private_key_headers', 9999 );

function bbloomer_conditional_private_key_headers( $headers_args ) {

	// PRODUCT ID HERE
	if ( ! bbloomer_product_id_in_cart( 12345 ) ) return $headers_args;

	// STRIPE Live Secret Key HERE
	$headers_args[ 'Authorization' ] = 'Basic ' . base64_encode( 'sk_live_..........' . ':' );

	return $headers_args;
}

Where to add custom code?

You should place custom PHP in functions.php and custom CSS in style.css of your child theme: where to place WooCommerce customization?

This code still works, unless you report otherwise. To exclude conflicts, temporarily switch to the Storefront theme, disable all plugins except WooCommerce, and test the snippet again: WooCommerce troubleshooting 101

Related content

  • WooCommerce: Cart and Checkout on the Same Page
    This is your ultimate guide – complete with shortcodes, snippets and workarounds – to completely skip the Cart page and have both cart table and checkout form on the same (Checkout) page. But first… why’d you want to do this? Well, if you sell high ticket products (i.e. on average, you sell no more than […]
  • WooCommerce: Disable Payment Method If Product Category @ Cart
    Today we take a look at the WooCommerce Checkout and specifically at how to disable a payment gateway (e.g. PayPal) if a specific product category is in the Cart. There are two tasks to code in this case: (1) based on all the products in the Cart, calculate the list of product categories in the […]
  • WooCommerce: Add Privacy Policy Checkbox @ Checkout
    Here’s a snippet regarding the checkout page. If you’ve been affected by GDPR, you will know you now need users to give you Privacy Policy consent. Or, you might need customer to acknowledge special shipping requirements for example. So, how do we display an additional tick box on the Checkout page (together with the existing […]
  • WooCommerce: Redirect to Custom Thank you Page
    How can you redirect customers to a beautifully looking, custom, thank you page? Thankfully you can add some PHP code to your functions.php or install a simple plugin and define a redirect to a custom WordPress page (as opposed to the default order-received endpoint). This is a great way for you to add specific up-sells, […]
  • WooCommerce: Disable Payment Gateway by Country
    You might want to disable PayPal for non-local customers or enable a specific gateway for only one country… Either way, this is a very common requirement for all of those who trade internationally. Here’s a simple snippet you can further customize to achieve your objective. Simply pick the payment gateway “slug” you want to disable/enable […]

Rodolfo Melogli

Business Bloomer Founder

Author, WooCommerce expert and WordCamp speaker, Rodolfo has worked as an independent WooCommerce freelancer since 2011. His goal is to help entrepreneurs and developers overcome their WooCommerce nightmares. Rodolfo loves travelling, chasing tennis & soccer balls and, of course, wood fired oven pizza. Follow @rmelogli

38 thoughts on “WooCommerce: Multiple Stripe Accounts (Solved)

  1. Ahoy all

    We found that with the new stripe UPE (Universal Payment Elements) gateway, the customer would get: “There was an error processing the payment: No such PaymentMethod: ‘pm_************'”

    When trying to complete payment.
    To solve this you need to also hook into `wc_stripe_upe_params`:

    add_filter( 'wc_stripe_upe_params', 'bbloomer_conditional_publishable_key_upe', 9999 );
     
    function bbloomer_conditional_publishable_key_upe( $params ) {
     
       // PRODUCT ID HERE
       if ( ! bbloomer_product_id_in_cart( 12345 ) ) return $params;
     
       // STRIPE Live Publishable Key HERE
       $params[ 'key' ] = 'pk_live_................';
     
       return $params;
    }
    

    I hope this saves you some precious time! โŒ›

  2. Hi Rodolfo,

    We are looking for a solution to switch between Stripe accounts according to a specific Geo Location based on the customer invoice and shipping adres. For example US customers to US Stripe account etc. Is this possible? And are you free for hire?

    1. Hi LB, thanks so much for your comment! Yes, feel free to contact me here

  3. Hello! We are having trouble getting this to swap out the accounts on our installation. Are you available for hire?

    1. Hello Mathieu, thanks for your comment! Yes, I already replied to your request via ClarityFlow, let me know if you managed to read it. Happy to help

  4. Hi there,

    Thanks for this awesome code. Pasting this into functions.php on latest WP/Woo/Stripe causes a fatal error for admin pages:
    Fatal error: Uncaught Error: Call to a member function generate_cart_id() on null

    I fixed by wrapping all your code in:

    if(!is_admin()) {
    }

    thanks

    1. Cool! Haven’t noticed this error on this website to be honest. When / where does this error trigger exactly?

  5. Hi, Businessbloomer owner!
    Is this possible to use this snippet multiple time for multiple products?

    I’m working for a client that need to be done that he is selling some physical products and digital product so he want to use multiple stripe account in their store.

    Please help me is this still works?

    1. What if I want to test that card what is the procedure for that?

      and is there anyway to confirm that 2nd account that I attached to my website using this snippet is successfully attached to the store.

      Thanks.

      1. Hi Shah, I use this snippet on this same website, based on product category (some categories go to Stripe A, some others to Stripe B). So, it works, yes! As for your questions, I can’t answer this here as it requires custom coding / consultation. In case, please get in touch privately. Thank you

  6. Hi,
    I used this snipped to send paiment to different accounts according to the country the products in the cart are related to.
    It worked great with standard payment method but I had to add “woocommerce gateway stripe” module to add Google Pay as payment method, and it doesn’t work anymore with this payment. The functions are just not called when Google Pay is used. But it still work with the other payment methods.
    Maybe just adding another filter would work, but I don’t know witch one…any ideas?

    Thanks

    1. Can’t really help without looking at your code – can you post it here or send it on to my email please?

  7. Hi there – is there a way to add another product ID? E.g.

    // -------------------
    // 2. Change Stripe keys on the go
     
    add_filter( 'wc_stripe_params', 'bbloomer_conditional_publishable_key', 9999 );
     
    function bbloomer_conditional_publishable_key( $params ) {
     
       // PRODUCT ID HERE
       if ( ! bbloomer_product_id_in_cart( 10241, 10242 ) ) return $params;
     
       // STRIPE Live Publishable Key HERE
       $params[ 'key' ] = 'pk_test_51J0WfbF5J9vPfugSzUg1gSJYYeGpW08Q1tOkUjMcsZ3zEyXw1eSLqOT72dhYHiu5Gr3c2zA8BQcQQxE4zNMmDCPO00blAgAaVp';
     
       return $params;
    }
     
    add_filter( 'wc_stripe_payment_request_params', 'bbloomer_conditional_publishable_key_request', 9999 );
     
    function bbloomer_conditional_publishable_key_request( $params ) {
     
       // PRODUCT ID HERE
       if ( ! bbloomer_product_id_in_cart( 10241, 10242 ) ) return $params;
     
       // STRIPE Live Publishable Key HERE
       $params[ 'stripe' ][ 'key' ] = 'pk_test_51J0WfbF5J9vPfugSzUg1gSJYYeGpW08Q1tOkUjMcsZ3zEyXw1eSLqOT72dhYHiu5Gr3c2zA8BQcQQxE4zNMmDCPO00blAgAaVp';
     
       return $params;
    }
     
    add_filter( 'woocommerce_stripe_request_headers', 'bbloomer_conditional_private_key_headers', 9999 );
     
    function bbloomer_conditional_private_key_headers( $headers_args ) {
     
       // PRODUCT ID HERE
       if ( ! bbloomer_product_id_in_cart( 10241, 10242 ) ) return $headers_args;
     
       // STRIPE Live Secret Key HERE
       $headers_args[ 'Authorization' ] = 'Basic ' . base64_encode( 'sk_test_51J0WfbF5J9vPfugS565HQlYeowCa3Rf5K5C0yLeqiKBhFNzrTkH0jQQkMx9dxjlspAE0FBECh8Q3rCeAhybKUfGZ00UnTyhYvN' . ':' );
     
       return $headers_args;
    }
    1. To follow on from this – could an Array be used to store multiple product ID’s and then the function looks for one of the ID’s and continues on?

      Hope that makes sense as I am a php noob

      thanks!

      1. Hi Kev, thanks so much for your comment! Yes, this is definitely possible, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  8. Note to others: This of course works exactly the same with TEST keys.

    For OP:

    First of all, THANK YOU !

    I made two business accounts in my Stripe account, each giving me uniques publishable and secret keys. Made one default and the other one I squeezed in for one product’s ID as the code intends and for a single purchase it works perfectly.

    Though I’m not sure I understand it correctly, the problem I stumbled upon is the following (note I’m testing it out in Test Mode).

    Let’s call a product using a default API keys DP (and DP1, DP2,… if need be) and the one using swapped API keys SP.

    If a new customer adds DP to cart, proceeds to checkout, payment goes through OK. Going back to the store and trying to redo everything the same again (ie purchasing DP or any other DPX) outputs error notification: `Sorry, we are unable to process your payment at this time.` If instead (or afterwards) we go back to the store and try to add SP instead of DP the error outputted is `No such source: ‘src_1IvSJ6HobZQAt8z5fZe2Lphl’`.

    Exactly the same scenario occurs if we swap SP and DP roles. So if a NEW customer purchases SP first it goes through fine. Changing to DP after purchase yields the same Source Error.

    At least in Test Mode (WP and Stripe.com) it often (and normally according to Stripe Support) duplicates the customer within a business account. If I try deleting both (of the same) customer(s) and retry payment, a customer is recreated in Stripe account, but WP front-end yields a new error `Sorry, we are unable to process your payment at this time. Please retry later.`

    Stripe allows you to have two customers with the same email in your business account, implying each of them has their own unique identifier. I think it naturally follows that same rules apply, if you have two customers with the same email address in different business accounts.

    So my question is: “Should there be more to this snippet to fetch and use customer source (UUID) and has anybody experienced similar issues and knows how to fix them?”

    Thanks in advance.

    1. Thanks for your feedback, I don’t think I’m able to reply to your questions though – customizing payment gateways is always a delicate operation

  9. I’m trying to use this snippet with a variable product, but it’s not working. I tried using the “master” ID for the product, and also de product IDs for the individual variations. Is there anything I should adjust to make this work with a variable product? Thanks!

    1. Hi Kavier, apparently the bbloomer_product_id_in_cart() function only works for simple products. Try this snippet alternative instead: https://www.businessbloomer.com/woocommerce-easily-check-product-id-cart/

  10. HI, first of all, thanks for your snippet.
    I try to adapt the snippet to look for a product tag in cart and not product ID.
    But can not complete the order, I get the notice error :

    No such source: 'src_xxx'
    

    and stripe error :

    {
      "error": {
        "code": "resource_missing",
        "doc_url": "https://stripe.com/docs/error-codes/resource-missing",
        "message": "No such source: 'src_xxx'",
        "param": "",
        "type": "invalid_request_error"
      }
    

    I could not fix it with the explanations of @Roel Broersma as I need code example (sorry for my coding level).

    Maybe I missed something, here is my code :

    add_filter( 'wc_stripe_params', 'conditional_publishable_key', 9999 );
     
    function conditional_publishable_key( $params ) {
    
       // set our flag to be false until we find a product in that tag
       $tag_check = false;
               
       // check each cart item for our category
       foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {      
             // If Cart has tag "formation-diplomante", set $tag_check to true
              if ( has_term( 'formation-diplomante', 'product_tag', $cart_item['product_id'] ) ) {
                  $tag_check = true;
                  break;
              }
       }
    
       if ( $tag_check ) {
          // STRIPE Live Publishable Key HERE
          $params[ 'key' ] = 'pk_test_';
       }
     
       return $params;
    }
     
    add_filter( 'wc_stripe_payment_request_params', 'conditional_publishable_key_request', 9999 );
     
    function conditional_publishable_key_request( $params ) {
    
       // set our flag to be false until we find a product in that tag
       $tag_check = false;
               
       // check each cart item for our category
       foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {      
             // If Cart has tag "formation-diplomante", set $tag_check to true
              if ( has_term( 'formation-diplomante', 'product_tag', $cart_item['product_id'] ) ) {
                  $tag_check = true;
                  break;
              }
       }
    
       if ( $tag_check ) {
          // STRIPE Live Publishable Key HERE
          $params[ 'stripe' ][ 'key' ] = 'pk_test_';
       }
     
       return $params;
    }
     
    add_filter( 'woocommerce_stripe_request_headers', 'conditional_private_key_headers', 9999 );
     
    function conditional_private_key_headers( $headers_args ) {
    
       // set our flag to be false until we find a product in that tag
       $tag_check = false;
               
       // check each cart item for our category
       foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {      
             // If Cart has tag "formation-diplomante", set $tag_check to true
              if ( has_term( 'formation-diplomante', 'product_tag', $cart_item['product_id'] ) ) {
                  $tag_check = true;
                  break;
              }
       }
    
       if ( $tag_check ) {
          // STRIPE Live Secret Key HERE
          $headers_args[ 'Authorization' ] = 'Basic ' . base64_encode( 'sk_test_' . ':' );
       }
     
       return $headers_args;
    }
    
    1. Hi David, thanks so much for your comment! Yes, this is definitely fixable, but I’m afraid it’s custom work. If you’d like to get a quote, feel free to contact me here. Thanks a lot for your understanding!

  11. Hi,

    thanks for the information. I am working on kinda the same problem – but instead of different accounts based on products in the cart, we use different accounts based on the shipping country.
    Sadly this makes it way more complex, since STRIPE precalculates CDATA on the page rendering. On the checkout page, when you change the country, this leads to a problem that the sources are not correctly registered at the different STRIPE endpoints leading to an error. So far all my efforts to manipulate the data during page runtime through js were useless, since the STRIPE js doesn’t take new data upon the “purchase” button press, but instantiates upon page load.
    I’m currently in contact with the STRIPE support team to figure out if there is a better way to achieve a correct behaviour, but I think I have to split up the billing/shipping information page and the payment page in order to have the correct pubkeys on pageload.

    All the best, J

      1. Hello @J and @rodolfo,
        I have faced the same issue on the checkout page, where I want to switch stripe account data on country change.
        But, it’s not changing on country change. it is changing on page reload. Can you please help me to do this point.?
        @J have you get any response from Stripe for the WooCommerce plugin?

        Thank you for reading my question.

        1. HI @rodolfo,
          Kindly look into my query. it is urgent for me. Also, if you have any alternative way then please let me know.

          Waiting for your response.

          Thank you,
          //Sagar

          1. Hi all,

            I’m facing a similar issue. I need to change the Stripe keys depending on a checkout custom field. If you can guide me with something I would appreciate it.

            Also, thanks for all the snippets and solutions you post, they are very helpful in so many cases.

            Thank you,
            Byron

        2. You could force a reload on country change?

  12. Hi Rodolfo,

    Thanks for writing this.
    Last year I made a plugin (named: ‘Stripe Supporter’) which will get the vendor ID of the product which is in the Cart (only 1 item in the cart is supported). Then it looks up the Stripe Keys for that Vendor (I extended the Vendor Edit form so vendors can edit their own Stripe Keys in here)

    It will then use the Vendor’s Stripe keys to do the Checkout.
    This way many people can built real open-source sharing platforms of I think is the future ๐Ÿ™‚ Money is not flowing through the platform anymore but directly from customer to vendor.

    However, while testing my plugin I noticed that when the payment is done and the customer is redirected to Woocommerce (return URL), Woocommerce sends some requests to Stripe with it’s master-Stripe account. Stripe then responds with 400-errors and

    {
      "error": {
        "code": "resource_missing",
        "doc_url": "https://stripe.com/docs/error-codes/resource-missing",
        "message": "No such token: 'src_xxxxxxxxxxxxxxxxxxxxxxxxx",
        "param": "source",
        "type": "invalid_request_error"
      }
    

    which is normal because the payment is made under a Vendor’s Stripe account and the Master Stripe account is not aware of this.

    Note: I already fixed the issue that on the return URL, there is no IN_CART object anymore, so you have to look at the ORDER-ID in the return url, i.e.: https://www.xxxxxxx.com/checkout/order-received/22045/?client_secret=src_client_secret_xxxxxxx&key=wc_order_xxxx… (in this case 22045) and then lookup the product vendor for this order.

    Have you also experienced some problems when using 2 Stripe accounts?

    PS. I will freely donate my plugin as open-source to the community once it’s v1.0 ๐Ÿ™‚

    1. I have fixed the issue. The problem was that Stripe notices the woocommerce webhook and then there is no order object or in_cart object. So it need to look at the json content that Stripe request/posts to the webhook. Sometimes there is not even an ->metadata->orderid so you can use the source_id and look that up in the order table.

      1. Good to know!

        1. If you have the code to fix the bug, feel free to share it here!

  13. Hey this does work anymore.

    Stripe requires you to pass the account number within the headers and Stripe js object initialization. As well as setting up a Connected accounts/Account platform.

    1. I find this strange, it’s a snippet I coded quite recently. Maybe your theme (or another plugin) is messing/conflicting with my snippet.

      To troubleshoot, disable all plugins but WooCommerce and also switch temporarily to “Twentytwenty” theme (load the snippet there in functions.php) as explained here: https://www.businessbloomer.com/lesson/trwm4l01/

      Once you do that, does it work? If yes, you have a problem with your current theme or one of the plugins.

      Hope this helps!

  14. The multiple Stripe accounts functionality comes so close to being what I need for an organization I work with. However, they would like multiple Stripe accounts to be included in a SINGLE form. This would allow donors to give to various causes within a single form, with the funds for each cause they donate to going to their respective Stripe accounts. Any chance this is a possibility with GiveWP?

    1. Not sure, did you ask GiveWP?

  15. Hey,
    Your content is rich, thank you, how if there are more than 1 product in cart?

    Thank you

    1. Good question, I recommend you force the cart to max one item: https://www.businessbloomer.com/woocommerce-allow-1-product-cart/

Questions? Feedback? Customization? Leave your comment now!
_____

If you are writing code, please wrap it like so: [php]code_here[/php]. Failure to complying with this, as well as going off topic or not using the English language will result in comment disapproval. You should expect a reply in about 2 weeks - this is a popular blog but I need to get paid work done first. Please consider joining the Business Bloomer Club to get quick WooCommerce support. Thank you!

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