#arnny221
1 messages · Page 1 of 1 (latest)
Hello! You shouldn't need to link a payment intent to a subscriptionn - you'd create the subscription first on your backend, and you'd get back a Payment Intent from the first Invoice that you can use with payment sheet
is this my backend,
const fetchPaymentSheetParams = async () => {
try {
const response = await api.post('/transactions/payment', {
amount: item.value,
customer_id: user.email
},);
const { client_secret, ephemeralKey, customer } = response.data;
console.log(client_secret)
console.log(ephemeralKey)
console.log(customer)
return {
client_secret,
ephemeralKey,
customer,
};
} catch (error) {
console.error('Erro ao buscar parâmetros do PaymentSheet:', error);
throw new Error('Erro ao buscar parâmetros do PaymentSheet');
}
};
const initializePaymentSheet = async () => {
const {
client_secret,
ephemeralKey,
customer,
publishableKey,
} = await fetchPaymentSheetParams();
const { error } = await initPaymentSheet({
merchantDisplayName: "Example, Inc.",
customerId: customer,
customerEphemeralKeySecret: ephemeralKey,
paymentIntentClientSecret: client_secret,
// Set `allowsDelayedPaymentMethods` to true if your business can handle payment
//methods that complete payment after a delay, like SEPA Debit and Sofort.
allowsDelayedPaymentMethods: true,
defaultBillingDetails: {
name: 'Jane Doe',
}
});
if (!error) {
console.log('não teve erro', error);
}
};
const openPaymentSheet = async () => {
const { error, paymentOption } = await presentPaymentSheet();
if (error) {
Alert.alert(`Error code: ${error.code}`, error.message);
} else {
Alert.alert('Success', 'Your order is confirmed!');
}
};
useEffect(() => {
initializePaymentSheet();
}, []); e my mobile app
Again, you don't need to be creating a separate payment intent - you'd create the Subscription first and then you'd get the paymetn intent from there
Do I create a subscription and then send a payment intention? to the front end?
Okay, it's clearer now
Can you help me with this?
Yes, you'd create your Subscription and if you expand the latest_invoice.payment_intent you should see the full payment intent that you can use with paymetn sheet
make this in this function ? const subscription = await stripe.subscriptions.create({
customer: user.stripe_customer_id,
items: [{ price: priceId }],
});
Yes, that's where you'd put the expansion for latest_invoice.payment_intent
const subscription = await stripe.subscriptions.create({
customer: user.stripe_customer_id,
items: [{ price: priceId }],
expand: ['latest_invoice.payment_intent']
}); like this ?
Yes
after this What should I do ?
Then you have the payment intent and you'd continue to use payment sheet
sureee , how do I send this to my paymentSheet?
I was under the impression you already had payment sheet working with a single payment intent? If so, then you'd do it's the same thing - you make the request to your server (which create the subscription) and your server send you back the payment intent
import { Stripe } from 'stripe';
interface PaymentIntentResponse {
client_secret: string;
ephemeralKey: string;
customer: string;
publishableKey: string;
}
const stripe = new Stripe(, {
apiVersion: '2023-10-16',
});
export async function createPaymentIntent(amount: number, customer_id: string): Promise<PaymentIntentResponse> {
try {
const customer = await stripe.customers.create({ email: customer_id });
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2023-10-16' }
);
const paymentIntent = await stripe.paymentIntents.create({
amount,
currency: 'brl',
customer: customer.id,
payment_method_types: ['card'],
use_stripe_sdk: true,
});
return {
client_secret: paymentIntent.client_secret || '',
ephemeralKey: ephemeralKey.secret || '',
customer: customer.id,
publishableKey:
};
} catch (error) {
console.error('Erro ao criar o PaymentIntent:', error);
throw new Error('Erro ao criar o PaymentIntent');
}
}
my route does this so, instead of creating a paymentIntent I do the signature method here and it will return a paymentIntent now?
I'm not sure what you mean by a signature method, but you'd essentially replace your payment intent creation request with what we just talked about
I'm sorry I typed it wrong, it's not a signature, it's a subscriptions
I'm Brazilian and my english isn't very good
no worries!
export async function createPaymentIntent(amount: number, customer_id: string, price_Id: string): Promise<PaymentIntentResponse> {
try {
// Criar o cliente no Stripe
const customer = await stripe.customers.create({ email: customer_id });
// Criar uma chave efêmera para o cliente
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customer.id },
{ apiVersion: '2023-10-16' }
);
// Criar uma assinatura para o cliente
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: price_Id }],
expand: ['latest_invoice.payment_intent']
});
// Verificar se há uma última fatura associada à assinatura
if (!subscription.latest_invoice) {
throw new Error('Não foi possível encontrar a última fatura da assinatura.');
}
// Obter o ID do PaymentIntent associado à primeira fatura da assinatura
const firstInvoice = await stripe.invoices.retrieve(subscription.latest_invoice as string);
const paymentIntentId = firstInvoice.payment_intent as string;
// Capturar o PaymentIntent
const capturedPaymentIntent = await stripe.paymentIntents.capture(paymentIntentId);
const client_secret = capturedPaymentIntent.client_secret || '';
// Retornar as informações relevantes
return {
client_secret,
ephemeralKey: ephemeralKey.secret || '',
customer: customer.id,
publishableKey: 'sua_chave_publica', // Substitua pela sua chave pública
};
} catch (error) {
console.error('Erro ao criar o PaymentIntent:', error);
throw new Error('Erro ao criar o PaymentIntent');
}
} i make this code but api returns error code 400 with this message: This customer has no attached payment source or default payment method. Please consider adding a default payment method
Can you help me with this?
Hi Karbi has to head out
Taking over
What line of code are you getting that error on?
I see
And what's the goal in the above code
To return client secret to the client so they can pay the first subscription invoice I assume?
Yeah so you need to set payment_behavior to default_incomplete when creating the sub then
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
but api return this
You're not setting payment_behavior to default_incomplete
oooo thats ok men, i make this on subscription same ?
sure i will see
If you want it to save the payment method as default after customer provides info you may also want to set this: https://stripe.com/docs/api/subscriptions/create#create_subscription-payment_settings-save_default_payment_method
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
What is it
Error: Stripe: Argument "invoice" must be a string, but got: [object Object] (on API request to GET /v1/invoices/{invoice})
Ok reading the rest of your code I have no idea why you're trying to capture the payment intent
Why are you?
I thought you said you were going to use the client secret to collect payment info
Why attempt to capture payment immediately like that?
It's because I'm using react-native-sdk on the client side and I wanted to purchase the subscription there
That doesn't make sense
You haven't collected payment info yet when running the above code, correct?
const capturedPaymentIntent = await stripe.paymentIntents.capture(paymentIntentId);```
This part makes no sense
Why did you add this?
You can't capture a payment intent if you don't have payment method info
sureee
Overall I'm really confused why you're doing those things in your code
What do I suggest to fix this?
Why did you add that?
I need to understand your reasoning in the first place?
I can't help unless I know exactly what you're doing
OK I'll try to explain
basically I'm trying to create a subscription and pay using the paymentSheet react-native-sdk it's the first time I'm doing this so I'm very confused so everything I see I'm trying.
Ok. Don't capture the payment intent
That has nothing to do with what you're doing. Not sure where you got the idea to do that
After creating the subscription, just return the client secret. That's all you need to do
You're getting an error on this line: const firstInvoice = await stripe.invoices.retrieve(subscription.latest_invoice as string);
because subscription.latest_invoice is an object
You need to pass its id
ie subscription.latest_invoice.id
Then just return the client secret on its payment intent. That's it
Don't try to capture it. You don't have a payment method yet
sure i will remove this from the code
it is saying that paymentIntent does not exist
What's with the quotes here?
// Retornar as informações relevantes
return {
client_secret,
ephemeralKey: ephemeralKey.secret '',```
Also send the exact error you're getting
Property 'payment_intent' does not exist in type 'string | Invoice'.
The 'payment_intent' property does not exist in type 'string'.
Weird. Can you log subscription.latest_invoice to see what's printed out after you create the subscription?
Oh it's not an api error then
It's a type error
Which you can suppress
Also you leaked your test secret key in here
Never share those publicly (even in test mode)
I deleted the message
It's ok
I think it worked, right?
Will this be a reoccurrence? Would I have to save the card details?
You definitely have an active subscription there
Yeah make sure you're setting this https://stripe.com/docs/api/subscriptions/create#create_subscription-payment_settings-save_default_payment_method
Complete reference documentation for the Stripe API. Includes code snippets and examples for our Python, Java, PHP, Node.js, Go, Ruby, and .NET libraries.
Otherwise if a default payment method isn't set, then the next payment will fail