#Max Savin

1 messages · Page 1 of 1 (latest)

heavy lintel
#

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.

cold orchid
#

Correction; I'm running:

const clone = await stripe.tokens.create({
customer: customerId,
}, {
stripeAccount: "acct_1Jk5j0RN2xWFXL74",
})

heavy lintel
#

Hm, can you elaborate a bit on why you're trying to create a token?

neon bloom
#

because our docs say to, but they're unfortunately really poor for cloning payment methods.

cold orchid
#

@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,
    });
heavy lintel
#

And that was returning an error?

cold orchid
#

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 (?)

heavy lintel
#

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.

cold orchid
#

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

heavy lintel
#

Taking a look

cold orchid
#
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'

heavy lintel
#

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?

cold orchid
#

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.

neon bloom
cold orchid
#

@neon bloom wouldn't passing in customer.id, paymentMethod and stripeAccount into paymentMethods.create effectively do that?

neon bloom
#

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

cold orchid
#

yes its not complete, it was based on tobys suggestion

neon bloom
#

yep

#

so to be clear on the overall steps:

#
  1. create Customer on the platform
  2. collect a PaymentMethod on the platform and attach it to that customer(you would generally do this using a SetupIntent + Elements on the platform)
  3. make that await stripe.paymentMethods.create API call using the platform customer and paymentmethod ID , plus stripeAccount
  4. you now have a PaymentMethod on the connected account
  5. pass that PaymentMethod to a PaymentIntent on the connected account(created with stripeAccount ) or 6) create a Customer (using stripeAccount) 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

cold orchid
#

For #2, is there any issue with using stripe.createPaymentMethod on the client and then running stripe.paymentMethods.create on the server?

neon bloom
#

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

cold orchid
#

yes, that is what I had before

#

oh.. I thought it does 3DS verification, etc

neon bloom
#

it is that yes, which is important

#

sorry, everything is complicated!

cold orchid
#

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'

neon bloom
#

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

cold orchid
#

paymentMethod_attach seems to be throwing the error

neon bloom
#

so where does paymentMethodId come from?

#

is it that frontend code you shared earlier that does

const stripe = Stripe("pk_test_D6G642gLuohUwC7BIondRNk2", {
    stripeAccount: gymId
});
cold orchid
#

from the client - I had omitted stripeAccount since its being created on the platform

neon bloom
#

hmm ok

cold orchid
#

one sec I may have made an errror

neon bloom
#

to clarify the code looks good to me

#

so not entirely sure why you'd get an error, but thinking

cold orchid
#

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}
neon bloom
#

oh you deleted the customer object

#

that's why you got "no such customer", it's not a Connect thing

cold orchid
#

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*

neon bloom
#

can you elaborate on that?

#

that code seems ok and it gets you to the end of step 4 in my steps above

cold orchid
#

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

neon bloom
#

no worries! not your fault, as I mentioned it's a really tricky API and we should document it better a lot better

cold orchid
#

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

neon bloom
#

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

cold orchid
#

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

neon bloom
#

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

cold orchid
#

ah yes, you can do on_behalf_of but then you can end up liable for the cash (i.e. chargebacks)

neon bloom
#

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

neon bloom
#

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