Open Closed

Stripe error: Can not complete a payment in 'Completed' state! #4974


User avatar
0
dkaczor created

Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples, to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, please use the search on the homepage.

If you're creating a bug/problem report, please include followings:

  • ABP Framework version: v7.1.0
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Steps to reproduce the issue:"

I'm creating a subscription for a new tenant:

var paymentRequest = await _subscriptionAppService.CreateSubscriptionAsync(EditionId, tenant.Id);
return LocalRedirectPreserveMethod("/Payment/GatewaySelection?paymentRequestId=" + paymentRequest.Id);

I have only Stripe configured so I am redirected to stripe payment page. I fill the data and submit the form. I get redirected back to my app and I see an error:

ApplicationException: Can not complete a payment in 'Completed' state! 
Volo.Payment.Requests.PaymentRequest.Complete()

It runs locally, so I use stripe CLI to forward the events to webhook:

stripe listen --forward-to https://localhost:44342/api/payment/stripe/webhook 
--events="customer.subscription.created,customer.subscription.deleted,customer.subscription.updated,checkout.session.completed"

I think it happens because the payment is completed in StripePaymentGateway.HandleWebhookAsync. and then in PostPayment page.


5 Answer(s)
  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Sorry, I couldn't understand the problem, do you get an exception? Can you share detailed exception?


    For subscriptions, configuring webhooks is required. The system can only know if subscription continues or not from webhooks.

    So, each subscription have to be checked and updated via webhooks. But the first payment for the subscription should be completed by both webhook and redirected last page, if not, it seems there is a missing use-case or a bug

  • User Avatar
    0
    dkaczor created

    Here are the logs:

    2023-04-28 15:03:57.651 +02:00 [INF] Executing endpoint '/Payment/Stripe/PostPayment'
    2023-04-28 15:03:57.654 +02:00 [INF] Route matched with {page = "/Payment/Stripe/PostPayment", action = "", controller = "", area = ""}. Executing page /Payment/Stripe/PostPayment
    2023-04-28 15:03:57.654 +02:00 [INF] Skipping the execution of current filter as its not the most effective filter implementing the policy Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy
    2023-04-28 15:03:57.658 +02:00 [INF] Executing handler method Volo.Payment.Stripe.Pages.Payment.Stripe.PostPaymentModel.OnGetAsync - ModelState is "Valid"
    2023-04-28 15:03:58.079 +02:00 [INF] Stripe session object: {
      "id": "cs_test_a1KwGMtweU2le8Q6e7qFYf4ZSBwfXTWf2ayUlE6blrP2O1R9z3jxsbozCf",
      "object": "checkout.session",
      "allow_promotion_codes": null,
      "amount_subtotal": 1000,
      "amount_total": 1000,
      "billing_address_collection": null,
      "cancel_url": "https://localhost:44342",
      "client_reference_id": null,
      "currency": "pln",
      "customer": "cus_NnRroLuNFjw3Vv",
      "customer_email": null,
      "line_items": null,
      "livemode": false,
      "locale": "auto",
      "metadata": {
        "PaymentRequestId": "07c4eda8-8676-82e7-ff15-3a0ada230abb"
      },
      "mode": "subscription",
      "payment_intent": null,
      "payment_method_types": [
        "card"
      ],
      "payment_status": "paid",
      "setup_intent": null,
      "shipping": null,
      "shipping_address_collection": null,
      "submit_type": null,
      "subscription": "sub_1N1qxpFhaWBJAQ5KtX3H5XCq",
      "success_url": "https://localhost:44342/Payment/Stripe/PostPayment?SessionId={CHECKOUT_SESSION_ID}",
      "total_details": {
        "amount_discount": 0,
        "amount_tax": 0,
        "breakdown": null
      }
    }
    2023-04-28 15:03:58.094 +02:00 [INF] Executed page /Payment/Stripe/PostPayment in 439.5326ms
    2023-04-28 15:03:58.094 +02:00 [INF] Executed endpoint '/Payment/Stripe/PostPayment'
    2023-04-28 15:03:58.110 +02:00 [DBG] Added 0 entity changes to the current audit log
    2023-04-28 15:03:58.110 +02:00 [DBG] Added 0 entity changes to the current audit log
    2023-04-28 15:03:58.115 +02:00 [ERR] An unhandled exception has occurred while executing the request.
    System.ApplicationException: Can not complete a payment in 'Completed' state!
       at Volo.Payment.Requests.PaymentRequest.Complete()
       at Volo.Payment.Stripe.StripePaymentGateway.CompleteAsync(Dictionary`2 parameters)
       at Volo.Payment.Requests.PaymentRequestAppService.CompleteAsync(String paymentGateway, Dictionary`2 parameters)
       at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
       at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
       at Volo.Abp.GlobalFeatures.GlobalFeatureInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
       at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
       at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
       at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
       at Volo.Abp.Auditing.AuditingInterceptor.ProceedByLoggingAsync(IAbpMethodInvocation invocation, AbpAuditingOptions options, IAuditingHelper auditingHelper, IAuditLogScope auditLogScope)
       at Volo.Abp.Auditing.AuditingInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
       at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
       at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
       at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
       at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
       at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
       at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo)
       at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1.ProceedAsync()
       at Volo.Abp.Uow.UnitOfWorkInterceptor.InterceptAsync(IAbpMethodInvocation invocation)
       at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1.InterceptAsync[TResult](IInvocation invocation, IInvocationProceedInfo proceedInfo, Func`3 proceed)
       at Volo.Payment.Stripe.Pages.Payment.Stripe.PostPaymentModel.OnGetAsync()
       at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.GenericTaskHandlerMethod.Convert[T](Object taskAsObject)
       at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.GenericTaskHandlerMethod.Execute(Object receiver, Object[] arguments)
       at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
       at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
       at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
       at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ExceptionContextSealed context)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
       at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
       at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
       at Volo.Abp.AspNetCore.Serilog.AbpSerilogMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
    --- End of stack trace from previous location ---
       at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Volo.Abp.AspNetCore.Auditing.AbpAuditingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
    --- End of stack trace from previous location ---
       at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
       at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
       at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
       at Volo.Abp.AspNetCore.Uow.AbpUnitOfWorkMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
    --- End of stack trace from previous location ---
       at Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Volo.Abp.AspNetCore.ExceptionHandling.AbpExceptionHandlingMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
    --- End of stack trace from previous location ---
       at Volo.Abp.AspNetCore.MultiTenancy.MultiTenancyMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
    --- End of stack trace from previous location ---
       at Microsoft.AspNetCore.Builder.ApplicationBuilderAbpOpenIddictMiddlewareExtension.<>c__DisplayClass0_0.<<UseAbpOpenIddictValidation>b__0>d.MoveNext()
    --- End of stack trace from previous location ---
       at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
       at Volo.Abp.AspNetCore.Security.AbpSecurityHeadersMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
    --- End of stack trace from previous location ---
       at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
       at Microsoft.AspNetCore.RequestLocalization.AbpRequestLocalizationMiddleware.InvokeAsync(HttpContext context, RequestDelegate next)
       at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
    --- End of stack trace from previous location ---
       at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
    2023-04-28 15:03:58.168 +02:00 [INF] Request finished HTTP/2 GET https://localhost:44342/Payment/Stripe/PostPayment?SessionId=cs_test_a1KwGMtweU2le8Q6e7qFYf4ZSBwfXTWf2ayUlE6blrP2O1R9z3jxsbozCf - - - 500 - text/html;+charset=utf-8 521.2704ms
    2023-04-28 15:03:58.202 +02:00 [INF] Request starting HTTP/2 GET https://localhost:44342/_vs/browserLink - -
    2023-04-28 15:03:58.211 +02:00 [INF] Request starting HTTP/2 GET https://localhost:44342/_framework/aspnetcore-browser-refresh.js - -
    2023-04-28 15:03:58.229 +02:00 [INF] Request finished HTTP/2 GET https://localhost:44342/_framework/aspnetcore-browser-refresh.js - - - 200 12030 application/javascript;+charset=utf-8 1.7892ms
    2023-04-28 15:03:58.260 +02:00 [INF] Request finished HTTP/2 GET https://localhost:44342/_vs/browserLink - - - 200 - text/javascript;+charset=UTF-8 57.9846ms
    2023-04-28 15:03:59.860 +02:00 [DBG] Executing HealthCheck collector HostedService.
    2023-04-28 15:03:59.861 +02:00 [INF] Start processing HTTP request GET https://localhost:44342/health-status
    2023-04-28 15:03:59.861 +02:00 [INF] Sending HTTP request GET https://localhost:44342/health-status
    2023-04-28 15:03:59.881 +02:00 [INF] Request starting HTTP/1.1 GET https://localhost:44342/health-status - -
    ...
    2023-04-28 15:03:59.883 +02:00 [INF] Executing endpoint 'Health checks'
    2023-04-28 15:03:59.889 +02:00 [DBG] Added 0 entity changes to the current audit log
    2023-04-28 15:03:59.889 +02:00 [INF] Executed endpoint 'Health checks'
    2023-04-28 15:03:59.889 +02:00 [INF] Request finished HTTP/1.1 GET https://localhost:44342/health-status - - - 200 - application/json 8.5741ms
    2023-04-28 15:03:59.902 +02:00 [INF] Received HTTP response headers after 40.9383ms - 200
    2023-04-28 15:03:59.902 +02:00 [INF] End processing HTTP request after 41.2369ms - 200
    2023-04-28 15:03:59.903 +02:00 [DBG] HealthReportCollector - health report execution history saved.
    2023-04-28 15:03:59.903 +02:00 [DBG] HealthReport history already exists and is in the same state, updating the values.
    2023-04-28 15:03:59.903 +02:00 [DBG] HealthReportCollector has completed.
    2023-04-28 15:03:59.903 +02:00 [DBG] HealthCheck collector HostedService executed successfully.
    
  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    You're right. It seems it's a false positive exception. We'll prevent this issue in the next 7.1 patch release.

    Since the check is done in the entity itself, unfortunately I can't provide a proper workaround until the next patch release.

  • User Avatar
    0
    dkaczor created

    I understand. Please let me know when the patch is released.

  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hi @dkaczor

    This is shipped with v7.2

    You can update your project to v7.2 to get the changes.

Made with ❤️ on ABP v9.1.0-preview. Updated on December 13, 2024, 06:09