Stripe.js 2 - Convert Payment Methods to Stripe token?

Hi there,

Anyone know if there is a way to convert saved payment method ID’s into Stripe Tokens?

I want to trigger the payment with the Stripe.js Element Action: “Start payment with Stripeelement” as that is the action which allows banks to come in between and verify the cardholder.

Using Stripe.js 2 there is a way to convert a card into a stripe token, however, I would like to use Payment Method ID’s instead to be SCA compliant whilst allowing users to save their cards (saving the payment method id’s).

Saving full card numbers and using the action “Convert card into a Stripe Token” would do the trick, but naturally, I do not want to save the full card details in my database. Also, I would not like my users to have to go through the step of always adding their card details…

Would there perhaps be another approach?
Or perhaps @copilot just could quickly update the plugin with “Convert Payment Method into a Stripe Token”?

Thx a lot for your support,


Or perhaps lifesavers @romanmg, @NigelG or @nicolas_dap might be able to save another life… :smiley:


My own life was saved by @copilot, @nicolas_dap and @ambroisedlg.

About the payment method, here’s how I finally learned to build something right :

(maybe you already knows all this, but maybe it could help anyway)

  1. drag&drop the Stripe Element

  2. with a button, trigger the event “Create payment method with Stripe Element”

  3. create 2 new events : “A payment method was created” and “A payment method couldn’t be created”.

In this last workflow (the one where things go right of course), here’s what I do :

  1. “Stripe.js Create a customer” (with first name, lastname, email of the current user, for example)

  2. Make change to User (Field “Stripe Customer ID” = result of step 1’s Customer ID)

  3. “Stripe.js Attach Payment Method” (PM id of the Stripe Element - Customer ID in the field you created at step 2)

  4. “Create a new PAYMENT METHOD” (a new DATATYPE you can create), where you store “This StripeElement’s Payment Method ID” in a new field (Stripe_pm_id for example), the Card Brand and the Last4 (just an example !) that you can get with “Stripe.js -Retrieve a PaymentMethod’s card brand or Card last4”. This is useful to show your customer he’s using this or that PM.

  5. Make change to User : in a new field called for example “Stripe_payment_method”, add the Result of step 4 (in my case, I needed to let the customer store many PM, so “ADD” was necessary).

  6. Clear Stripe element

Alert your customer with alert or whatever.

Hope that helps.



Yupp, thx a lot.

That’s how I’ve built it and it works just fine.

My question lies with how I can attach a payment method (that has earlier been created) with a Stripe Element? As the Stripe Element (which has been dragged and dropped to the page) functions as the link to trigger the payment using the action “Start a payment with Stripe Element”.

When creating a payment method you activate the Stripe Element - right? And as a result you can use the action “Start a payment with Stripe Element”.

Would there be a way to activate the Stripe Element using a stored Payment Method ID, that’s the key issue/question here…?

As far as I understood all this (and I’m really not a specialist), you don’t have to pass or attach any PM to the Stripe Element in itself.

I think that what you’re missing is the concept of “Client Secret”.

Let’s try this :

After having build all the process of the message above…

  1. you just have to create a PaymentIntent (without trying to confirm it). That’s where you simply “attach” your PaymentMethod (meaning setting its id in the correct parameter)

  2. get the PaymentIntent’s Client secret with some Retrieve action : "Stripe.js - Retrieve a PaymentIntent’s client_secret (you’ll be asked the PI’s id)

  3. put this Client Secret in some Custom State

  4. with some button, use the Stripe.js action “Start payment with StripeElement”. That’s where you need your Client Secret. Your MAGICAL Client Secret I should say :slight_smile:

  5. Then you create the 2 events “Payment was Successful” and “Payment was unsuccesful”, as for the PM.

1 Like

Thanks again Michel for your support!

Oh so you’re saying that I actually don’t need the Stripe Element to be “activated”, instead just

    1. Retrieve the CS (client secret) from the payment intent (using the earlier stored PM id
    1. Start payment with stripe token (using the CS from step 1).
    1. Confirm the payment intent in case of the event “Payment was Successful”.

I’ll try that directly early morning - hopefully it works (sounds logical, don’t know why I didn’t test that :smiley:).

Appreciate your help Michel!


I hope too :slight_smile:

Referring to your list :

  1. you will be asked the PI id, not the PM id.

  2. By Stripe Token, I guess you mean Stripe Element

  3. You don’t have to confirm the Payment Intent. As soon as you launch the Stripe.js action “Start payment with StripeElement”, Stripe will try to confirm the PI, and if things are ok, then it’s firing some Serverside action, that you can visualize thanks to the WF event “Payment was successful”. If not, that’s the other Event (Payment was usuccessful) that is fired.

That’s really great, because in both cases, you can fire some workflow and warn your user (and yourself) that things went ok or not.

There’s indeed an action called “confirm PaymentIntent”, but it’s to be used only if you don’t want to use the Element, the Client secret, etc. But I think this is not encouraged, as it lets you without any confirmation that the payment was really confirmed.

Good luck !


Hi Michel,

I’m unfortunately reverting to you with this one…

Have you built a workflow where you use stored payment methods and use the “Start payment with Stripeelement”?

In my case the checkout flow only works when I create a new payment method as follows:
Step 1. Store customer id as a state (from database if logged in, otherwise create new customer)
Step 2. Ask the user to input their card information (Stripeelement)
Step 3. Use that info to create a payment method
Step 4. Store that payment method’s id as a state
Step 5. Create a payment intent using that store payment method id and customer id
Step 6. Start payment with stripe element

However, when I practically skip steps 2 & 3 and instead refer to a stored payment method id for this specific customer, it throws the following error:

Screenshot 2020-07-14 at 8.51.00

Would you be able to check in your workflow if this occurs when you refer to stored payment methods? (as I understand that you’ve built your workflow in the same way…)

Thx again,


Hi Jonas,

I got no such error, and I’m building a platform where the customer is proposed to store as much payment methods as he wants to . Then, I got no issue to let them use any previously stored PM for any new Payment Intent.

I see 2 path you could investigate in :

  • did you attach the PM to the Customer ? I’m not sure, but I think this is mandatory to get things working properly (use Stripe.js - PaymentMethod - Attach once you got the Customer ID and the PM ID) ;

  • could you try with some homemade API call, not using the Copilot plugin ? I met a least one situation where things didn’t want to work with the plugin, and then suddenly worked like a charm as soon as I used my own calls.

If you don’t know how to do this, and if it’s scarying you (I was), please note I didn’t even know one week ago I could do this by myself. In fact, that’s (almost) easy.



Hi Michel,
Those homemade API calls would after all have been great.
I’m just not really getting them “accepted” when trying to using the API Connector (although practically I’ve even tried to copy from Stripe’s docs the JSON and import it using the “import using JSON”.

Any tips to get these homemade API calls really going…?


Hi Von!

How did you go with the API calls ?

Slowly getting a hang of it. :smiley:

I ended up using both Stripe.js 2 in combination with a homemade API call that “clones” a payment method on a connected account.

Related to the problem described in this topic, it actually was very simple. When using stored payment methods, one needs to “disable” the Stripeelement used. So in the checkout you have 2 different Stripelements - one for new payment methods (which is “enabled”) and one for stored payment methods (which is “disabled”). This way the 3DSecure also works with saved payment methods.


Great idea Von. I’m trying to add such a feature on my cosmetics shop and it seems to work well. I actually got the idea of implanting such a payment method after reading this article about Reducer and how easily you can save a buck or two by going against the usual payment gateways on your website. I never knew that there was so much to process when dealing with money coming in to your hands and the amount that you lose by choosing an expensive provider who rips you off on processing fees.

Yep that’s how it unfortunately is. Even relatively big SaaS services offered to entrepreneurs just go with a 3% industry standards payment processing fee (which is actually quite a lot of bullshit). Practically just doing this because they are ripping off and relying on a somewhat simple product that is not able to identify the associated payment processing fees that with Stripe practically just depend on currency and card issuing country.

Hey Von, could you please share a screenshot of what your homemade API call looks like, i am struggling with the payment clone part … Thanks!

Thanks @michelduprez I was on this for days and I set up your process in 20 min! Works like a charm.

Do you know how do the same thing but for subscription?

Also, how do you create an invoice after the payment?

Thanks a lot!

A subscription example would be great!

Hi @vonhertzen.jonas @michelduprez

It’s been a long time since you seems to have resolved the issue, but I am currently encountering the exact same problem as yours.

Here is my workflow:

  • a user signs up on my platform = we create a customer ID.
  • in his own settings, a user can add multiple payment methods. In the backend, we 'create a new PM" and then ‘attach this new PM’ to the customer ID (with all the required fields i.e. PM id etc)
  • in the checkout section, the user has two options: to use a saved payment method, or to create a new payment method (which will be saved automatically). When a user creates a new PM, it is done using the action ‘Create a new PM with StripeElement…’.

Then, let’s say the user wants to use a saved card, here is the workflow:
1- ‘Start PaymentIntent - Create’, using the current user’s Customer ID
2- ‘Start payment with StripeElement X’, using Client Secret Result of step 1’s client secret, Generate payment is No, and using the payment method ID of the selected saved card. (which is saved as a custom state within the page)

But then, it stops working and I get the following message:

From what I’ve understood, it works ONLY when the user creates a PM using the StripeElement X, which generates a StripeElements PM ID. And I cannot figure out what I am doing wrong.

I haven’t understood what you said about the 2 different stripelements… and it seems I am in the exact same position as you were a few months back. Would be so kind as to giving me hand?

Looking forward to hearing from you !!

Hello there,

Just wondering if you ever found a solution to this? I am having the same issue and it’s driving me up the wall.

Thank you!

Bump. I am facing the same issue, did anyone find a solution? @phdom @vonhertzen.jonas @alexis1 @michelduprez