Search code examples
c#asp.net-corestripe-paymentsruntime-error

Asp.Net - Stripe payment intent working locally but error 502 online


I'm trying to build a custom payment flow using Stripe. It's working locally, but when I try to put it online, I get an error after a certain time. I asked my web hosting service if they put any filter, but apparently not. You'll find the code bellow. For the Javascript, I basically copy pasted the code given by Stripe. Also, I don't get any payment intent on the Stripe end, so I think my web app can't connect to Stripe. Visually the form where the user is supposed to enter his card number etc isn't appearing.

The error I get after a certain time on the payment intent page error image

The server side code (C#):

[Authorize]
[Route("/create-payment-intent")]
[ApiController]
public class PaymentIntentApiController : Controller
{
    private readonly UserManager<AppUser> userManager;
    private readonly ApplicationDbContext db;

    public PaymentIntentApiController(UserManager<AppUser> userManager, ApplicationDbContext db)
    {
        this.userManager = userManager;
        this.db = db;
    }

    [HttpPost]
    public async Task<ActionResult> Create(ProductViewModel request)
    {
        if (request == null)
        {
            return RedirectToAction("Checkout", "Payment");
        }

        ComplexDbOperations cdo = new ComplexDbOperations(db);
        Data.Objects.Product product = new Data.Objects.Product { period = request.period, sub = request.subscription };

        int price = ProductViewModel.calculateStripePrice(await cdo.getPricesAsync(product.ToRole().ToString()));
        if (price <= 0)
        {
            return RedirectToAction("Checkout", "Payment");
        }

        AppUser user = await userManager.GetUserAsync(User);
        if (user == null) return RedirectToAction("Index", "Home");

        var paymentIntents = new PaymentIntentService();

        var paymentIntentOptions = new PaymentIntentCreateOptions
        {
            Amount = price,
            Currency = "chf",
            Description = string.Format("Abonnement {0} pour {1}, Periode : {2}", request.subscription.ToString(), user.Email, request.period.ToString()),
            Metadata = new Dictionary<string, string>
              {
                {"Abonnement", request.subscription.ToString()},
                {"Periode", request.period.ToString() },
                {"UserId", user.Id },
                {"UserEmail", user.Email },
                {"subCode", ((int)request.subscription).ToString()},
                {"periodCode", ((int)request.period).ToString() },
              }
        };

        var paymentIntent = paymentIntents.Create(paymentIntentOptions);
        return Json(new { clientSecret = paymentIntent.ClientSecret });
    }
}

    

What I've modified from Stripe on the client side code (js) :

// The items the customer wants to buy
var purchase = {
    period: parseInt(document.getElementById("period").value),
    subscription: parseInt(document.getElementById("subscription").value)
};

// Disable the button until we have Stripe set up on the page
document.querySelector("button").disabled = true;
fetch("/create-payment-intent", {
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify(purchase)
})... (stripe code continuing)

Can you please help me ? I don't even know how I can get more details on the error as I can't debug the program when it's online.

Thanks in advance.

[Update] I logged the server error and got :

System.Net.Http.HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. (api.stripe.com:443)

Solution

  • I finally know what was the problem so I'll explain what it was and how to solve it if someone encounters the same error.

    The first thing I did was, as suggested by karllekko, to check the server logs when it was running on the hosted service. For that, I used Serilog which is a package that allows you to store the logs into a file (It was the simpliest solution for me). I then got a more precise error :

    HttpRequestException: A connection attempt failed because the connected party did not properly respond after a period of time...

    From this error, I knew I wasn't able to get to stripe's servers. I found a simple ping function in C# that checks if my assumption was right and it was.

    I then checked with my host service provider how I could access an external IP: they use a proxy server for security reasons.

    I added this code before creating the payment intent which uses the proxy server :

    var handler = new HttpClientHandler
    {
        Proxy = new WebProxy(proxyServer),
        UseProxy = true,
    };
    var httpClient = new HttpClient(handler);
    
    var stripeClient = new StripeClient(
        apiKey: secretApiKey,
        httpClient: new SystemNetHttpClient(httpClient)
    );
    StripeConfiguration.StripeClient = stripeClient;
    

    I hope if someone encounters the same error he will be able to solve the problem with this answer.