#holykent
1 messages ยท Page 1 of 1 (latest)
Hello ๐
Can you move the code into the thread?
try
{
var confirmedPaymentIntent = await retryPolicy.ExecuteAsync(async () => await _paymentIntentService.ConfirmAsync(paymentIntentId));
var status = MapToCustomStatus(confirmedPaymentIntent.Status);
if (confirmedPaymentIntent.Status is StripePaymentIntentStatus.RequiresAction)
{
return new ConfirmPaymentDetails(confirmedPaymentIntent.Id, status, confirmedPaymentIntent.ClientSecret);
}
return new ConfirmPaymentDetails(confirmedPaymentIntent.Id, status);
}
catch (StripeException ex)
{
...
}
catch (HttpRequestException ex)
{
...
}
Sorry
All good. taking a look
mainly im confused about how stripe handles "errors", i would like to recall reading that they are all translated into exceptions, and there is no such status as "failed" so therefore failed payments throw exceptions?
Sorry for the delay here
no worries
Do you have an example PaymentIntent ID I can take a look at to make sure I am on the same page about how you're creating these Intents?
public async Task<Result<CreatePaymentDetails>> CreatePayment(decimal amount, Currency currency, string? token, long reservationId)
{
var options = new PaymentIntentCreateOptions
{
Amount = (long)amount,
Currency = currency.ToString(), // Listing's currency
PaymentMethodTypes = new List<string> { StripePaymentMethods.Klarna, StripePaymentMethods.Card },
ConfirmationMethod = "manual",
TransferGroup = reservationId.ToString(),
};
// Klarna needs only the client secret so this wont apply to klarna.
if (token is not null)
{
options.PaymentMethod = token;
}
var retryPolicy = StripePolicies.TransientAndStripeExceptionRetryPolicy();
try
{
var paymentIntent = await retryPolicy.ExecuteAsync(async () => await _paymentIntentService.CreateAsync(options, new RequestOptions
{
IdempotencyKey = reservationId.ToString()
}));
return new CreatePaymentDetails(paymentIntent.Id, paymentIntent.ClientSecret, PaymentStatus.Unknown);
}
catch (StripeException ex)
{
var customStripeErrorResponse = StripeExtensions.GetCustomStripeErrorMessage(ex);
Log.Error(ex, customStripeErrorResponse.Message);
return new CreatePaymentError(customStripeErrorResponse.Message);
}
catch (HttpRequestException ex)
{
Log.Error(ex, "Network issues prevented the creation of the payment intent object. Please try again soon.");
return new CreatePaymentError(ex.Message);
}
}
I just realized I dont attach a paymentmethodId to paymentintents when it's klarna payment as the client only needs the client secret (i think?)
but either way, i just want to know if it's safe to assume the payment is "successful" if confirmasync doesnt throw an exception. If not, I'd like to know what other states it could be in.
I'm assuming it cannot be failed as that status does not exist, so immediate failure = exception, no?
with confirmAsync the payment can fail later on. There are two ways you can make sure it succeeded
1/ Poll the API to retrieve the PaymentIntent and checking its status
OR
2/ Implement webhooks and listen to payment_intent.succeeded events
that way you can be 100% sure
I have a webhook, for my internal system, there are no issues as I undo reservations if payment is not successful within 15 minutes. That's just my own system.
But what do I tell the client/customer? No exception was thrown... when is it safe for me toi display to him "Purchase successful"?
after my ConfirmAsync code above, we can be assured no exception was thrown if it returns the detail response. But it could be required_action or processing or successful. It can't immediately be any failed state, right?
Ah yeah if the confirm call itself doesn't throw any errors then yeah you can assume the payment details were sent successfully to the API
do I just poll an endpoint to check the status for like.. let's say 10 seconds, spinning a wheel, and if the status is not successful within 10 seconds i'll just display "We're processing hte payment. Please check your mail soon"
or some such?
and if it succeeds within 10 seconds just display success
do I just poll an endpoint to check the status for like.. let's say 10 seconds, spinning a wheel, and if the status is not successful within 10 seconds i'll just display "We're processing hte payment. Please check your mail soon"
With it being async, it would be a good idea to poll the API
yup, that should work
ah yes right i can poll it directly from the client
im a backend developer so i know nothing about the frontend basically
but yes that makes sense
You can play around with the test cards here to trigger diff scenarios
https://stripe.com/docs/testing#declined-payments
but anyway, to make sure, here, i can basically assume that at least the call was successful and that any errors that may occur with the payment here are errors out of my control?
var confirmPaymentResult = await _paymentGateway.ConfirmPayment(createPaymentResult.Value.PaymentId);
if (!confirmPaymentResult.IsSuccess)
return Results.BadRequest(confirmPaymentResult.Error.Message);
if (confirmPaymentResult.Value.PaymentStatus is PaymentStatus.RequiresAction)
return Results.Ok(confirmPaymentResult.Value.ClientSecret);
return Results.Ok(confirmPaymentResult.Value.PaymentStatus);
and after that reutnr to the client, it's up to the client to decide if its appropriate to show the "Successful purchase" page?
that's correct
LOL NP! ๐ Happy to help
oh just one more question before you close this, at this stage, is one of the reasons it could be unsuccessful due to insufficient funds? or is that caught by the exception?
provided a paymentmethodId was already attached to the paymentintent
ConfirmAsync checks the paymentmethod has sufficient funds, yes?
Hmm not sure with the call being async, testing it would help you confirm the expected beahvior faster
Would recommend using the test cards on the link I shared above