Stripe - Refund Checkout Session - javascript

I’m trying to implement a method for my connected account owners to be able to refund charges collected via a Stripe Checkout Session.
In order to do so, I want to use the following code:
const refund = await stripe.refunds.create({
payment_intent: pi_id,
});
In order to obtain the payment_intent_id, I am listening to the checkout.session.completed webhook, and accessing data.object.payment_intent.
When I attempt to create a refund using this payment intent id, I get the No such paymentintent error from Stripe. I noticed in my Stripe test account that there is a charge ID associated with the payment, so maybe I should be using that - but I’m not sure how to retrieve that programmatically from the checkout session.

You're making the API call correctly.
“No such...” errors with Stripe are usually caused by either a mismatch in API keys (e.g. using a mixture of your test plus live keys) or by trying to access objects that exist on a different account (e.g. trying to perform an operation from your platform account on an object that was created on a connected account).

Related

How to get payout data in Stripe Connect?

I'm adding Stripe Connect to my app to send payments to the users,I need to create a payment dashboard where each user can see all the payments that were sent to them( like payment history). I've read here https://stripe.com/docs/api/payouts/create that I can retrieve list of all payouts or individual payout(by submitting payout id), but I can't find information on how to get payout data per user. For example, if I have user John Doe, I want to get all the payout information for John only with 1 API call, is it possible in Stripe Connect?
If you want to retrieve the list of payments on the connected account, you should retrieve the list of Charges using the stripeAccount header.
You can also make use of the auto-pagination built into Stripe SDKs to loop through the list.
Example
for await (const charge of stripe.charges.list({stripeAccount: 'connected_account_id'})) {
// Do something with charge
console.log(charge);
}
You may want to reach out to Stripe to check if you're eligible to use this beta where you can embed a payments dashboard component into your site : https://stripe.com/docs/connect/get-started-connect-embedded-uis
If I understand goodly your question, you want to retrieve connected accounts' payouts.
You have to know that payout api using is when you move money on your account. In the other hand, if you want to move money to any connected account you need to use transfert api.
Code
You need to know user connect account
const stripe = require('stripe')('API_KEY');
const transfers = await stripe.transfers.list({
destination: 'acct_id.....',
});

Stripe connect transfers and payouts without verification

I am trying to clarify things associated with Stripe Connect's paymentIntent and transfers endpoints. The thing is that I do think that I do not understand the flow perfectly and even do not know if I did choose the best solution for my application.
I am using the separate charges and transfers method and for the account type I did choose custom.
What I want to achieve is the following:
Get money from user A and send it to user B (user in this context is my platform user not the Stripe Account or Customer). I want to take my cut while I send the money to user B. It leads to a question, if I do need to create both the Stripe Customer and Account. And if the user B who gets the money after transfer is not acting as a company, why would I need to collect industry and other legal information from him/her just to make payout?
What I did:
First of all I do create Stipe Customer and Account for my platform users. Then I:
Create PaymentIntent to take money from (Stripe Customer A). Includes the Stripe fees
Create Transfer of the PaymentIntent and transfer it to (Stripe Account B).
Now I want to create payout of the transferred money. Do I have to trigger the payout endpoint for this case?
The 3 last steps in code:
Create paymentIntent
const paymentIntent = {description, amount, currency, customer_id, transfer_group, payment_method, confirmation_method: 'manual', confirm: true};
const response = await stripe.paymentIntents.create(paymentIntent);
Create transfer
const transfer = { amount, currency, destination: destinationAccount, transfer_group };
const response = await stripe.transfers.create(transfer);
stripe.paymentIntents.confirm(response.client_secret, {payment_method: response.payment_method})
Now money is taken from Customer A and transferred to Account B but I have no idea what legal information I need from my platform users to be able to create payouts? All my Stripe accounts/customers did accept the tos_acceptance also while adding a new source. None of my platform users are industry nor a company. They are individuals doing their things.
To follow the flow which you mentioned you need to create stripe Connect account for each of your customer B. As you need to do payouts to there bank accounts they need to be completely verified by stripe this shows legal information required for verification as per country
Though your end users are individuals you need to completely prove them for authenticity as you are involving them in legal fund transfer and making there sub-merchant accounts.
And you don't have to trigger the payout end point as it is automatically handled by stripe and you can also change it either you want to do payout weekly/daily/monthly etc and also set for custom payouts from dashboard settings.

How do I check Stripe coupon validity in Stripe elements?

I'm trying to check coupon validity while using a stripe elements form on the client side without going to server. The idea is that I want to tell a customer if their coupon is valid or invalid before signing them up for something.
Ideally I would be able to just do something like this:
stripe.coupons.retrieve(coupon).then((stripe_coupon)=> {
createToken(additionalData);
}).catch((error) => {
throwCardError("Invalid coupon, please try again.");
});
The issue is that stripe.coupons is not a part of the elements API, it's only part of the server-side API.
The reason I'm hesitant to check on the server side is because I use firestore to store all my data. So that means in order to get this to work, I would have to first write the coupon to firebase, have a cloud function that calls the stripe API to check the coupon validity and then writes that to a separate part of the database just for that, and then set up a listener on the client side that listens for changes to that part of the database to check coupon validity, and all of that would be really slow.
Is there any way to check the validity of a stripe coupon client side in stripe elements?
There is no function within Elements to check the validity of a coupon (you can see all available methods for Stripe.js / Elements here).
If you're using Firebase, what you can do here is setup an endpoint using a HTTP function, in your client-side code make a request to this endpoint using fetch, passing the coupon id you wish to check.
When this request hits this endpoint you will make a call out to the Stripe API to attempt to retrieve the coupon, returning the result to the user; there's no need to store a copy of the coupon within your Firebase database.

Retrieve Stripe charge status from used source token - Node + MongoDB

Let's say my user submits a credit card token to my server to complete a purchase. Then I save this token in my user's cart, and in the sequence, I charge it.
I receive a success response with the charge id and, suddenly, my server stops working just before I can store this charge id in my user's cart.
The charge was definitely made, but I couldn't save it in my database to generate the user's order and make the products available, so I don't know if it succeeded or not.
What I want to do is to mitigate any possibility of duplicate payments. I've looked into the entire Stripe's API but I just couldn't find any information about if it's possible to retrieve a charge using the card token that was used to create it.
Every time when my server reboots, some processes are triggered to verify database integrity (I'm using MongoDB, by the way), and one of those processes tries to make charges for all user carts (with already generated card tokens) that were left in a "waiting payment" state. If a card token wasn't charged yet, everything works well, but if it was charged already, I just don't know if the charge succeeded or not, so I can't update my cart to a consistent state.
I can retrieve the card token by using "stripe.tokens.retrieve(token).then(...", but I just know if it was used or not. I have to find a way to discover if it was charged and if it succeeded.
I've tried to store the card token as a metadata of my charge, so I'd be able to retrieve charges that contain this card token as metadata, but it seems that this kind of query is not possible.
Does anyone know how to overcome this issue or any better logic to grant payment consistency in a MongoDB payment implementation?
As #karllekko commented, this is the answer to my question:
"You can generate and save a unique ID at the beginning of the cart checkout attempt, and use this as an idempotency key when making the charge request : stripe.com/docs/api#idempotent_requests Then if you have a crash, you can safely retry the request, and if you use the same key, it won't create a duplicate charge(you just get the original response back)"
And following my logic, I'm making those failed payments attempts to be executed again without the need of the user to retry it manually, so I'm storing the card-token generated client-side in my user's cart and in the sequence I'm charging this same token and using it as the idempotency key to avoid duplicate payments, as they are unique within Stripe's DB.
This is the request that avoids duplicate payments and always gives me the same response, successful or not, for the same card-token, and makes it possible to grant a consistent state to my user's cart:
stripe.charges.create(
{
amount: amount,
currency: 'usd',
source: token
},
{
idempotency_key: token
}
).then(
res => resolve(res),// Proceed to a success card/order state and allow products/services to be accessed by user. If an attempt of make duplicate payments using the same card-token happens, you'll receive the same success response and will be able to proceed to the same success card/order state.
err => reject({e: err, m: 'PAYMENT_ERROR', i: 'STRIPE_CHARGE_ERROR'})// An error occurred with the original charge request, so you'll have to rollback to the pre-checkout cart state. Even if you couldn't get the original error response, using an idempotency key will give you the exactly same error response in this step when you retry the charge attempt for this same card-token, so you know you have to rollback.
)
Thanks, #karllekko!

Handling successful payment processing but database update failure

I am trying to implement a stripe checkout process in one of my express.js routes. To do this, I have:
Official Node.js Stripe module
Official client-side Stripe module
A json logger I use to log things like javascript errors, incoming requests and responses from external services like stripe, mongodb, etc…
An Order model defined using mongoose - a MongoDB ODM
My steps are as follows:
Client:
Submit order details which include a stripe payment token
Server:
Create an unpaid order and save to database (order.status is created)
Use stripe client to charge user's credit/debit card
Update order and save to database (order.status is accepted or failed depending on response from Stripe)
Question: If payment is successful after step 2 but an error occurs updating the order in step 3 (due to database server error, outage or similar), what are some appropriate ways to handle this failure scenario and potentially recover from it?
With payment systems, you always need a consolidation process (hourly, daily, monthly) based on sane accounting principles that will check that every money flow is matched.
In your case, I suggest that every external async call logs the sent parameters and the received response. If you do not have a response within a certain time, you know that something has gone wrong on the external system (Stripe, in your case) or on the way back from the external system (you mention a database failure on your side)
Basically, for each async "transaction" that you spawn, you know when you start it and have to decide of a reasonable amount of time before it ends. Thus you have an expected_end_ts in the database.
If you have not received an answer after expected_end_ts, you know that something is wrong. Then you could ask for the status to Stripe or another PSP. Hopefully the API will give you a sane answer as to whether the payment went through or not.
Also note that you should add a step between 1. and 2 : re-read the database. You want to make sure that every payment request you make is really in the database, stored exactly as you are going to send it.

Categories