#Max Savin
1 messages · Page 1 of 1 (latest)
Oh no, let's see what we can do about that!
Pasting your other message for context:
I run: const customer = await stripe.customers.create({ source: "cus_KRZYiVn9Op4wTr" }, {stripeAccount: 'acct_1Jk5j0RN2xWFXL74',});
I get: Error: The customer must have an active payment source attached.
Correction; I'm running:
const clone = await stripe.tokens.create({
customer: customerId,
}, {
stripeAccount: "acct_1Jk5j0RN2xWFXL74",
})
Hm, can you elaborate a bit on why you're trying to create a token?
because our docs say to, but they're unfortunately really poor for cloning payment methods.
you want to do https://stripe.com/docs/payments/payment-methods/connect#cloning-payment-methods instead of creating a token if the Customer uses PaymentMethods pm_xxx , we badly need to completely rewrite these docs.
@neon bloom I'm actually trying right now. you can hire me to do it haha I've been battling it for two weeks now
never thought I would resort to contacting support lol
nvm, I was actually trying:
const customer = await stripe.customers.create({
payment_method: paymentMethodId,
}, {
stripeAccount: gymDoc.stripeId,
});
And that was returning an error?
Error: No such PaymentMethod: 'pm_1Jn0KkEorjmXmtcurk9MeiOk'; OAuth key or Stripe-Account header was used but API request was provided with a platform-owned payment method ID. Please ensure that the provided payment method matches the specified account.
I am guessing I need to specify the Connect account key on the client side when creating payment method... playing with it now... but then I can't use the card on my platform (?)
So a platform can makes requests for itself or for its connected accounts, but the resources within each account do not get shared. In this case the payment method that you're trying to use resides on the platform account, but the request where you're trying to use it is being done for the connected account.
I believe that is if you use on_behalf_of , but then you risk chargebacks. when you charge directly on the connected account, the disputes are on their end
const customer = await stripe.customers.create({
name: userDoc.profile.name,
email: userDoc.emails[0].address,
}, {
stripeAccount: gymDoc.stripeId,
});
const paymentMethod = await stripe.paymentMethods.create({
customer: customer.id,
payment_method: paymentMethodId,
}, {
stripeAccount: gymDoc.stripeId,
});```
Error: No such customer: 'cus_KRuF3o3qloFR18'
The customer is being created on the connect account, but the paymentMethod call does not work
Taking a look
const gymId = "acct_1Jk5j0RN2xWFXL74";
const stripe = Stripe("pk_test_D6G642gLuohUwC7BIondRNk2", {
stripeAccount: gymId
});
stripe.createPaymentMethod({
type: 'card',
card: card,
billing_details: {
name: 'Jenny Rosen',
}, {
stripeAccount: gymId
}).then(function(result) {
console.log(result)
});
If I take out stripeAccount from the stripe initialization, I get:
Exception while invoking method 'membership/stripe/addPaymentMethod' Error: No such customer: 'cus_KRuUzltkrsWOtC'
Sorry about the delay! When you're trying to clone the paymentMethod, could try providing the Customer ID from the platform account rather than the newly created customer on the connected account?
Exception while invoking method 'membership/stripe/addPaymentMethod' Error: No such PaymentMethod: 'pm_1Jn0iiRN2xWFXL74dznByjkF'
I removed stripeAccount from the client
and ran:
const customer = await stripe.customers.create({
name: userDoc.profile.name + "fuck",
email: userDoc.emails[0].address,
});
console.log(customer)
const paymentMethod = await stripe.paymentMethods.create({
customer: customer.id,
payment_method: paymentMethodId,
}, {
stripeAccount: gymDoc.stripeId,
});
that worked, but there's no credit card on the account
correction: the account was only created on my platform, not on the Connect account, and there is no card attached to it
However, there was no error. I got back: "cus_KRubIxuFryDv0J" and "pm_1Jn0m0RN2xWFXL74QPHkQP0f"
For some context: I am building an app for gyms to charge their members for classes or for memberships. All that I really need is just to save the credit card and charge it via the application. I'm using the PaymentMethod API as the 3DS verification, etc, is great to have.
yep, you didn't add one so that seems expected
@neon bloom wouldn't passing in customer.id, paymentMethod and stripeAccount into paymentMethods.create effectively do that?
it would create a PaymentMethod on the connected account, cloning its details from the existing PaymentMethod on the platform yes
the snippet you shared above I don't think works in isolation, it creates a Customer on the platform(with no card like you say) and then tries to clone .. something(what was paymentMethodId ) even though there's nothing on that platform customer to clone so I assume that is not a complete snippet
yes its not complete, it was based on tobys suggestion
yep
so to be clear on the overall steps:
- create Customer on the platform
- collect a PaymentMethod on the platform and attach it to that customer(you would generally do this using a SetupIntent + Elements on the platform)
- make that
await stripe.paymentMethods.createAPI call using the platform customer and paymentmethod ID , plusstripeAccount - you now have a PaymentMethod on the connected account
- pass that PaymentMethod to a PaymentIntent on the connected account(created with
stripeAccount) or 6) create a Customer (usingstripeAccount) on the connected account and attach the PaymentMethod to that
this is all assuming you want to do this kind of cloning set up ,where you have a Customer object on the platform that has a bunch of payment methods it owns and manages, and then you can clone from there to specific connected accounts to do a Direct Charge(charging those details on the connected account)
but that's the basic outline of it
For #2, is there any issue with using stripe.createPaymentMethod on the client and then running stripe.paymentMethods.create on the server?
you wouldn't use stripe.paymentMethods.create on the server in that flow, you'd use stripe.paymentMethods.attach
you can do that but I think we prefer/recommend using SetupIntents and never using that create-then-manually-attach flow as it can have issues with declines
it is that yes, which is important
for example attaching the card might fail because 3D Secure was required on the validation charge involved (https://support.stripe.com/questions/unexpected-1-charge-on-customers-bank-statement)
sorry, everything is complicated!
so I'm running:
// Function to grab the customerId OR generate one via Stripe
// get saved customerId or create and save one .. code omitted
const getCustomerId = async function () {
const customer = await stripe.customers.create({
name: userDoc.profile.name,
email: userDoc.emails[0].address,
});
return customer.id
};
// Grab the customerId OR generate one via Stripe
const customerId = await getCustomerId();
// Attach the paymentMethod to the customerId
const paymentMethod_attach = await stripe.paymentMethods.attach(paymentMethodId, {
customer: customerId
});
// // Make it the default payment method
const updateCustomer = await stripe.customers.update(customerId, {
invoice_settings: {
default_payment_method: paymentMethodId,
}
});
// Do what karllekko said
const paymentMethod = await stripe.paymentMethods.create({
customer: customer.id,
payment_method: paymentMethodId,
}, {
stripeAccount: gymDoc.stripeId,
});
return {customerId, paymentMethod_attach, updateCustomer, paymentMethod}
returns:
Error: No such customer: 'cus_KRZYiVn9Op4wTr'
which specific call returns that?
also I think you want to use paymentMethod_attach in the "make it the default" and "karllekko" snippets though I don't think it should matter
paymentMethod_attach seems to be throwing the error
so where does paymentMethodId come from?
is it that frontend code you shared earlier that does
const stripe = Stripe("pk_test_D6G642gLuohUwC7BIondRNk2", {
stripeAccount: gymId
});
from the client - I had omitted stripeAccount since its being created on the platform
hmm ok
one sec I may have made an errror
to clarify the code looks good to me
so not entirely sure why you'd get an error, but thinking
so I just ran:
const customer = await stripe.customers.create({
name: userDoc.profile.name + "god help me",
email: userDoc.emails[0].address,
});
console.log({customer})
// Attach the paymentMethod to the customerId
const paymentMethod_attach = await stripe.paymentMethods.attach(paymentMethodId, {
customer: customer.id
});
console.log({paymentMethod_attach})
// // Make it the default payment method
const updateCustomer = await stripe.customers.update(customer.id, {
invoice_settings: {
default_payment_method: paymentMethodId,
}
});
console.log({updateCustomer})
// Do what karllekko said
const paymentMethod = await stripe.paymentMethods.create({
customer: customer.id,
payment_method: paymentMethodId,
}, {
stripeAccount: gymDoc.stripeId,
});
console.log({paymentMethod})
return {customer, paymentMethod_attach, updateCustomer, paymentMethod}
oh you deleted the customer object
that's why you got "no such customer", it's not a Connect thing
this code executes and it creates an account on the platform with a credit card
BUT it does not get carried over the Connect account*
can you elaborate on that?
that code seems ok and it gets you to the end of step 4 in my steps above
this is good
Ah sorry lol
one sec
holy shit it works
Karllekko I am forever indebted to you 🥲
I'm going to write a tutorial if you'd like, and will def mention your help
no worries! not your fault, as I mentioned it's a really tricky API and we should document it better a lot better
I had been with stripe chat support and reading docs for days
I really think it can be just one or two API calls
and... I think its a very common use case (?) but I have no idea what things look like on Stripe side
it's somewhat common, since if you want to do Direct Charges this is a common way to want to do things, a 'master' customer managed by the marketplace and then charging it on behalf of individual merchants, people do use it(there was another thread here on Discord doing the same thing right now as well). I wish we invested a bit more, I'll continue to push! Glad you're unblocked
yes haha I even emailed the founder of Stripe haha
so I guess, beyond this, you need to sync the customer on your platform and on Connect accounts manually
like if they enter their account, you have to attach it your platform, then copy it into each account
that's my final question haha
generally yes you have to sync manually
it depends if you do 5) or 6) in my steps
you can either just have the customer on the platform, copy their payment method, charge it on the connected account as a one-off , and then do that each time you need a payment
ah yes, you can do on_behalf_of but then you can end up liable for the cash (i.e. chargebacks)
or you can have the customer on the platform, copy their payment method, save it to a Customer on the connected account, and then keep the two in sync by re-cloning any new cards added on the platform
well yes, to be clear all of what we've talked about here is related to using Direct Charges
which is where the connected account processes the payment and takes liability/fees
you could of course completely avoid all this by using Destination charges where you process the payment as the platform with the Customer/PaymentMethods all simply managed on that one account, and transfer the raw money to the connected accounts (on_behalf_of lets you brand the payment like they are processing it).
I have to run, hopefully you're unblocked