#ding-subscription

1 messages ยท Page 1 of 1 (latest)

jagged folio
jagged folio
#

Hi there, sorry for the delay.

#
        payment_intent: data.paymentIntentId,
        amount: 4825,
        reverse_transfer=true
    });```
wicked sentinel
#

I actually tried this reverse_transfer attr before

#

and got this error from my backend log

#

Unhandled error StripeInvalidRequestError: The recipient of this transfer does not have sufficient funds in their Stripe balance to reverse this amount.

#

which doesnt make sense to me

#

because when the payment is done, connect account receive some money

#

why is it saying insufficent fund

jagged folio
#

If the connected account has a balance that is less than e.g. $43.25 in this scenario, this error would result.

#

This could be e.g. the amount available for Connect account has already been payout to the user's bank account.

wicked sentinel
#

Okay.

#

I think I come up another solution that might solve my problem but I need a bit of your help

jagged folio
#

I would recommend debiting amount back to the Connected account in order to allow the reversal to occur successfully.

#

Sure thing!

wicked sentinel
#

I see that

#

when payment is completed

#

a transfer is created

#

And I got that transfer Id from webhook

#

So I think reverse that transfer solve my probelm

#

However, I think the transfer is created due to this code

#

exports.createSubCheckout = functions.https.onCall(async (data, context) => {
const session = await stripe.checkout.sessions.create({
line_items: [
{
price: data.priceId,
quantity: 1,
},
],
subscription_data: {
application_fee_percent: 14.1,
transfer_data: {
destination: 'acct_1KEbRFGIsavKxBch',
},
},
metadata: {
permitId: data.id,
subscribed: data.subscribed,
},
customer_email: data.email,
payment_method_types: ['card'],
mode: 'subscription',
success_url: ${data.url}/my-permits,
cancel_url: ${data.url},
});
return session.id;
});

#

but in my webhook that listens to transfer.created has empty metadata

#

๐Ÿฅฒ

#

Do you know where I can pass metadata so that it shows on the webhook that listens to transfer.created

#

I thought passing metadata to this checkout session will make it appear in the webhook that listens to transfer.created

#

If it sounds confusing to you, can i call you through discord to explain it a bit more please ?

#

This has been bugging me for hours โ˜น๏ธ

#

Basically what I am saying is, this transfer.created event is not coming from stripe.transfers.create, it is coming from subscribe checkout session, so i don't know where I can pass data to its metadata

#

I think this transfer event is when Stripe transfer money to the connect account

jagged folio
#

The metadata set in this scenario would be available in the webhooks related to Checkout, e.g. checkout.session.completed

wicked sentinel
#

yea I know

#

but I want to pass metadata to this transfer event

#

not the checkout.session.completed

#

I know I can pass the metadata if i am creating this transfer like this

#

I know I can pass the metadata if i am creating this transfer like this: const transfer = await stripe.transfers.create({
amount: 400,
currency: 'cad',
destination: 'acct_1KEN5sIiEock6T4N',
transfer_group: 'ORDER_95',
metadata:{blablabbla}
});

#

but this time the transfer is not coming from stripe.transfers.create

#

its like an extra event coming from the check out session

#

I am sorry if this sounds super confusing, but do you get what my problem is now ? ๐Ÿ˜€

jagged folio
#

Thank you for the clarification, please let me check if this is doable ๐Ÿ™‚

wicked sentinel
#

thanks

wicked sentinel
#

Are you still with me ๐Ÿ˜‰

jagged folio
#

yes, sorry, I am currently inspecting if the metadata is a part of the subscription_data, would this be reflected in the transfer object's metadata.

wicked sentinel
#

๐Ÿ‘ ok ok thx!!

#

I will wait!!

jagged folio
#

Hi there, sorry for the wait. It seems the other metadata field is tied to Subscription.

wicked sentinel
#

the transfer metadata ?

jagged folio
#

I would recommend to listen to the checkout.session.completed event.
If you were to retrieve this Session object [0] and expand by the PaymentIntent object [1], this is where you can see the Charge objects [2], which contains the Transfer Id [3].

[0] https://stripe.com/docs/api/checkout/sessions/retrieve
[1] https://stripe.com/docs/api/checkout/sessions/object#checkout_session_object-payment_intent
[2] https://stripe.com/docs/api/payment_intents/object#payment_intent_object-charges
[3] https://stripe.com/docs/api/charges/object#charge_object-transfer

#

After obtaining this Transfer id, you can then update the metadata field

wicked sentinel
#

let me have a look

jagged folio
wicked sentinel
#

const session = await stripe.checkout.sessions.create({
line_items: [
{
price: data.priceId,
quantity: 1,
},
],
subscription_data: {
application_fee_percent: 14.1,
transfer_data: {
destination: 'acct_1KEbRFGIsavKxBch',
},
},
metadata: {
permitId: data.id,
subscribed: data.subscribed,
},
customer_email: data.email,
payment_method_types: ['card'],
mode: 'subscription',
success_url: ${data.url}/my-permits,
cancel_url: ${data.url},
});
return session.id;
});

#

I am not sure what to do for the first step(retrieve session )

#

I see this from the doc: const session = await stripe.checkout.sessions.retrieve(
'cs_test_a1FkiPfLi5Ytc61Gvjd1s5w509E99YGigU7Qwn1w6e9b0t7MDyAQwJP9wD'
);

jagged folio
#

After you have received the checkout.session.completed event, the checkout id should be provided by the event, this is the id you could use to retrieve the Checkout Session object

wicked sentinel
#

even I follow the steps, and finally got the transfer id.

#

But the above lines were already called

#

where am i going to pass this transfer id

#

the transfer id should have go in here : metadata: {
permitId: data.id,
subscribed: data.subscribed,
},

#

I did retrieved the session object as you suggested, the paymentIntent was null

jagged folio
#
  'cs_test_xxx', {
    expand: ['payment_intent'],
  }
);

const payment_intent = session.payment_intent;
const charges = payment_intent.charges.data
const transfer_id = charges[0].transfer

// Update the Transfer with the metadata
const transfer = await stripe.transfers.update(
  'tr_3KFAlEFQX5wP7o0y0XRHtnNn',
  { metadata: {
    permitId: xxx,
    subscribed: xxx
  }
}
);
jagged folio
wicked sentinel
#

ok i think I did it wrong

#

I dind't do the expand

#

I was just checking the session object

#

let me try the above code see if i can get the transfer id!!

#

const session = await stripe.checkout.sessions.create({
line_items: [
{
price: data.priceId,
quantity: 1,
},
],
metadata: {
permitId: data.id,
subscribed: data.subscribed,
},
customer_email: data.email,
payment_method_types: ['card'],
mode: 'subscription',
success_url: ${data.url}/my-permits,
cancel_url: ${data.url},
});

const retrieveSession = await stripe.checkout.sessions.retrieve(session.id, {
    expand: ['payment_intent'],
});

const paymentIntent = retrieveSession.payment_intent;
const charges = paymentIntent.charges.data;
const transferId = charges[0].transfer;

return transferId;
#

Trying

#

If I am able to return the correct transferId, then you save my life ๐Ÿ™‚

#

Does the code look right to you? I am just waiting it to upload

#

Unhandled error TypeError: Cannot read property 'charges' of null

#

const session = await stripe.checkout.sessions.create({
line_items: [
{
price: data.priceId,
quantity: 1,
},
],
metadata: {
permitId: data.id,
subscribed: data.subscribed,
},
customer_email: data.email,
payment_method_types: ['card'],
mode: 'subscription',
success_url: ${data.url}/my-permits,
cancel_url: ${data.url},
});

const retrieveSession = await stripe.checkout.sessions.retrieve(session.id, {
    expand: ['payment_intent'],
});

return retrieveSession;
#

Gonna try this, see what it returns

#

req_u0ynPqH0c0DGP0

#

retrieveSession.payment_intent = undefined

#

check the above requestId

#

it should show the same, payment intent null

jagged folio
#

This is because the current payment status is: unpaid, therefore there is no respective PaymentIntent object associated to the Checkout

wicked sentinel
#

ok let me try it again!!

wicked sentinel
#

is there a way to

#

pass sessionid into the metadata of checkoutsession.create

jagged folio
#

Session id is created when the Checkout Session is created.

wicked sentinel
#

sry

#

that was a stupid question

#

lol

jagged folio
#

As you are creating a subscription, an alternative way would be to have the metadata passed into the Subscription, in this case, it would allow update of metadata ๐Ÿ˜„

jagged folio