0
votes

I am following the docs here about enabling other business to accept payments directly.

I have successfully created a connected account and accepted a payment from a customer on the connected account, but I have not yet been able to save that customers payment information for future payments.

All across the documentation, especially here it assumes you already created a customer on the platform account WITH a payment method, before you should try and clone the payment method to the connected accounts.

I cannot for the life of me figure out how to create a customer with payment information on the platform account before I clone them on the connected account.

As per the documentation, I started here on the client side where the accountID is the ID of the connected account:


const [stripePromise, setstripePromise] = useState(() =>
    loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, {
      stripeAccount: uid.accountID,
    })
  );

My Stripe Elements are created with the stripePromise.

When trying to save the card details I do this on the client side:

This is where I believe my mistake is I am using the connected accounts credentials while trying to create a platform payment method.

  const handleRememberMe = async () => {
    const { token } = await stripe.createToken(
      elements.getElement(CardElement)
    );
    console.log(token);

    const res = await fetchPostJSON("/api/pay_performer", {
      accountID: accountID,
      amount: value,
      cardToken: token,
    });

That API call goes to "/api/pay_performer":

//Handle onboarding a new connect user for x

require("dotenv").config();
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
  apiVersion: "2020-08-27",
});
import setCookie from "../../../utils/cookies";

export default async function createPayment(req, res) {
  if (req.method === "POST") {
// Connected account ID and the token generated on the client to be saved.
    const { accountID, amount, cardToken } = req.body;
    console.log(`API side cardToken: ${cardToken.used}`);
    try {
      // Trying to create a customer with that token.
      const customer = await stripe.customers.create({
        email: "test2@example.com",
        source: cardToken.card,
      });
      customer.sources = cardToken.card;
// Beginning the cloning process for the connected account.
      const token = await stripe.tokens.create(
        {
          customer: customer.id,
        },
        {
          stripeAccount: accountID,
        }
      );
      const clonedCustomer = await stripe.customers.create(
        {
          source: token.id,
        },
        {
          stripeAccount: accountID,
        }
      );
      console.log(`Default Source: ${clonedCustomer.default_source}`);

      console.log(`AccountID: ${accountID}, Amount: ${amount}`);
      const paymentIntent = await stripe.paymentIntents.create(
        {
          payment_method_types: ["card"],
          payment_method: clonedCustomer.default_source
            ? clonedCustomer.default_source
            : null,
          amount: amount * 100,
          currency: "usd",
          application_fee_amount: 1,
          customer: clonedCustomer.id,
        },
        {
          stripeAccount: accountID,
        }
      );

      const secret = paymentIntent.client_secret;
      console.log(secret);
      const payment_method = paymentIntent.payment_method;
      return res.status(200).send({ secret, payment_method });
    } catch (e) {
      console.log(e);
      return res.status(500).send({ error: e.message });
    }
  }
}

But I get an error that the token provided is not a valid token. I am assuming this is because I created the token using the credentials for the connected account on the client and then tried to apply it to the platform account.

How do I have a separate UI to create platform customers FIRST, and then come back and clone them to the connected accounts upon purchase.

Should I not pass a token to the server and just pass the card information over HTTPS? Very lost and the documentation has not helped!

Any help is appreciated!

1

1 Answers

0
votes

In order to create a Customer, collect card information and attach a PaymentMethod to them, you could for example use a SetupIntent and Elements [1] or create a PaymentMethod [2]. The core point being, if the system should initially store that information on the platform, the connected account isn't coming into play at all yet. Broadly speaking the steps are (not providing the account id of the connected account anywhere as this is only happening on the platform account), using the platform's secret key:

  1. Create a customer
  2. Collect card data using Stripe.js and Elements
  3. Attach the pm_xxx to the customer in the backend

[1] https://stripe.com/docs/payments/save-and-reuse

[2] https://stripe.com/docs/js/payment_methods/create_payment_method