已解决 - 条带克隆客户并在关联账户上创建直接收费

Solved - Stripe Clone Customer and Create Direct Charge on Connected Account

我正在尝试在 Stripe 中的关联帐户上创建直接收费。我一直在浏览 Stripe 上的文档并在此处发帖,但似乎无法正常工作。

客户及其付款方式存储在平台帐户中。我正在尝试在连接的帐户上克隆客户,但不想将他们的付款方式存储在连接的帐户上。根据文档,我可以通过不将其附加到我试图在关联帐户上创建的客户来生成一次性使用的付款意向。

尝试克隆客户时出现错误:

StripeInvalidRequestError: The customer must have an active payment source attached.

在下面的代码中,我确保付款方式附加到平台客户,当我转到控制台时,我看到他们的付款方式并标记为“默认”。

感谢任何帮助!


const customerId = 'cus_xxx'; // platform customer id
const paymentMethod = 'pm_xxxx'; // platform customer payment method

const getDefaultCard = async (customer) => {
  const { invoice_settings } = await stripe.customers.retrieve(customer);
  return invoice_settings ? invoice_settings.default_payment_method : null;
};

const getCards = async (customer) => {
  if (!customer) {
    return [];
  }
  const default_card = await getDefaultCard(customer);
  const { data } = await Stripe.stripe.paymentMethods.list({
    customer,
    type: "card",
  });
  if (!data) return [];
  return data.map(({ id, card: { last4, exp_month, exp_year, brand } }) => ({
    id,
    last4,
    exp_month,
    exp_year,
    brand,
    default: id === default_card,
  }));
};

// check to see if the current payment method is 
// attached to the platform customer
const cards = await getCards(customerId);

let found = cards.filter((card) => card.id === paymentMethod).length > 0;

// if the card is not found, attach it to the platform customer
if (!found) {
  const res = await Stripe.stripe.paymentMethods.attach(paymentMethod, {
    customer: customerId,
  });
}

const defaultCards = cards.filter((card) => card.default);

if (!defaultCards || !defaultCards.length) {
  // attach a default payment source to the user before
  // cloning to the connected account
  await stripe.customers.update(user.cus_id, {
    invoice_settings: {
      default_payment_method: paymentMethod,
    },
  });
}


// Get customer token - Results in ERROR
const token = await stripe.tokens.create(
  {
    customer: customerId,
    card: paymentMethod,
  },
  {
    stripeAccount,
  }
);

/** DOESN'T GET PAST TOKEN CREATION ABOVE **/

// clone customer
const newCustomer = await stripe.customers.create(
  {
    source: token.id,
    card: paymentMethod,
  },
  {
    stripeAccount,
  }
);

const amount = 1000;
const application_fee_amount = 100;

const intent = await Stripe.stripe.paymentIntents.create(
  {
    customer: newCustomer.id,
    amount,
    currency: "usd",
    payment_method_types: ["card"],
    payment_method: paymentMethod,
    description: "Test Connected Direct Charge",
    application_fee_amount,
  },
  {
    stripeAccount,
  }
);

// Now confirm payment
const result = await Stripe.stripe.paymentIntents.confirm(intent.id, {
  payment_method: paymentMethod,
});

您似乎正在尝试将平台帐户上的付款方式克隆到关联帐户上的令牌。这不可能;付款方式是较新的 Stripe API,不直接与令牌兼容(较旧的 API)。

您应该 cloning the Payment Method on the platform to a Payment Method on the connected account 而不是使用这样的代码:

const paymentMethod = await stripe.paymentMethods.create({
  customer: '{{CUSTOMER_ID}}',
  payment_method: '{{PAYMENT_METHOD_ID}}',
}, {
  stripeAccount: '{{CONNECTED_ACCOUNT_ID}}',
});

我能够通过首先确保平台上存在用户的支付方式来解决这个问题。然后在我的付款意向中,以下成功克隆了客户和付款方式并成功收费:

// clone payment method
const cloned_pm = await stripe.paymentMethods.create({
        customer,         // platform customer id
        payment_method,   // platform payment method for platform customer
      },{
        stripeAccount
      });

// create token to customer
const token = await stripe.tokens.create({
          customer,              // platform customer id
          card: payment_method,  // platform payment method as above
      },{
          stripeAccount
      });

// clone customer
const newCustomer = await stripe.customers.create({
          source: token.id,
      },{
          stripeAccount
      });

// create intent - used the cloned customer and payment methods
const intent = await stripe.paymentIntents.create(
        {
          customer: newCustomer.id,
          amount: 1000,
          application_fee_amount: 100,
          currency: "usd",
          payment_method_types: ["card"],
          payment_method: cloned_pm.id,    
          ...         
        },
        {
          stripeAccount,
        }
      );

然后在前端客户端:

const { error, paymentIntent } = await stripe.confirmCardPayment(
      payment_intent_secret,
      { payment_method: cloned_payment_method_id }
    );