#holykent

1 messages ยท Page 1 of 1 (latest)

brazen craterBOT
rustic oxide
#

Hello ๐Ÿ‘‹
Can you move the code into the thread?

high smelt
#
 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

rustic oxide
#

All good. taking a look

high smelt
#

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?

rustic oxide
#

Sorry for the delay here

high smelt
#

no worries

rustic oxide
#

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?

high smelt
#
 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?

rustic oxide
#

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

high smelt
#

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?

rustic oxide
#

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

high smelt
#

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

rustic oxide
#

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

high smelt
#

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

rustic oxide
high smelt
#

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?

rustic oxide
#

that's correct

high smelt
#

nice, btw i hate hanzo haha

#

thanks for the help

rustic oxide
#

LOL NP! ๐Ÿ™‚ Happy to help

high smelt
#

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?

rustic oxide
#

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

high smelt
#

Yes ill check them out, thx

#

well since there is a card fr insufficient funds decline, im assuming it must throw an exception of type card_error upon confirmasync