Reputation: 115
I'm using .NET and Stripe to make a webshop, and I'm trying to figure out how to redirect a customer to a success page, once the charge has been successfull. However Stripe recently changed their API, and I've been unable to find any resources online explaining how to do this.
I've tried creating a webhook that listens to the charge.succeeded event, and I can get the event to trigger, but I'm unable to redirect the customer to any page from the webhook.
Another thing I've tried is in the checkout page where I've added method="post" to the form, and type="submit" and formmethod="post" to the button respectively, so that when the customer clicks "Pay," the customer is redirected through the post method of the checkout page, but I can't get the post method to run.
Checkout razor page:
<head>
<title>Checkout</title>
<script src="https://js.stripe.com/v3/"></script>
</head>
<--! This is where I've tried method="post", type="submit" and formmethod="post" -->
<form id="payment-form">
<div id="card-element">
<!-- Elements will create input elements here -->
</div>
<!-- We'll put the error messages in this element -->
<div id="card-errors" role="alert"></div>
<button id="submit">Pay</button>
</form>
@section scripts{
<script>
// Set your publishable key: remember to change this to your live publishable key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
var stripe = Stripe('{PUBLIC KEY}');
var elements = stripe.elements();
window.onload = function () {
// Set up Stripe.js and Elements to use in checkout form
var style = {
base: {
color: "#32325d",
}
};
var card = elements.create("card", { style: style });
card.mount("#card-element");
card.addEventListener('change', function (event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
var form = document.getElementById('payment-form');
form.addEventListener('submit', function (ev) {
ev.preventDefault();
stripe.confirmCardPayment('@Model.ClientSecret', {
payment_method: {
card: card,
billing_details: {
name: '@Model.CustomerInformation.FirstName',
email: '@Model.CustomerInformation.Email',
address: {
city: '@Model.CustomerInformation.City',
line1: '@Model.CustomerInformation.Address1',
postal_code: '@Model.CustomerInformation.ZipCode'
}
}
}
}).then(function (result) {
if (result.error) {
// Show error to your customer (e.g., insufficient funds)
console.log(result.error.message);
} else {
// The payment has been processed!
if (result.paymentIntent.status === 'succeeded') {
// Show a success message to your customer
// There's a risk of the customer closing the window before callback
// execution. Set up a webhook or plugin to listen for the
// payment_intent.succeeded event that handles any business critical
// post-payment actions.
}
}
});
});
};
</script>
Webhook:
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Stripe;
namespace workspace.Controllers
{
[Route("api/[controller]")]
public class StripeWebHook : Controller
{
// If you are testing your webhook locally with the Stripe CLI you
// can find the endpoint's secret by running `stripe listen`
// Otherwise, find your endpoint's secret in your webhook settings in the Developer Dashboard
const string endpointSecret = "ENDPOINT SECRET";
[HttpPost]
public async Task<IActionResult> Index()
{
var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
try
{
var stripeEvent = EventUtility.ParseEvent(json);
// Handle the event
if (stripeEvent.Type == Events.PaymentIntentSucceeded)
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
Console.WriteLine("Successful!");
return Ok();
}
else if (stripeEvent.Type == Events.ChargeSucceeded)
{
Console.WriteLine("Successful!");
// This is where I've tried return RedirectToPage("/Index");
return Ok();
}
else if (stripeEvent.Type == Events.PaymentIntentCreated)
{
Console.WriteLine("Successful!");
return Ok();
}
else if (stripeEvent.Type == Events.PaymentMethodAttached)
{
var paymentMethod = stripeEvent.Data.Object as PaymentMethod;
Console.WriteLine("PaymentMethod was attached to a Customer!");
}
// ... handle other event types
else
{
// Unexpected event type
return BadRequest();
}
return Ok();
}
catch (StripeException e)
{
return BadRequest();
}
}
}
}
Upvotes: 2
Views: 2788
Reputation: 1179
I think that we should iron out a few concepts here first. The webhook endpoint is a standalone API that lives in your system somewhere and reacts to Events that are posted to it from Stripe, such as the charge.succeeded
Event.
Your Elements implementation in the browser is completely separate and can't respond to anything that your webhook endpoint can return in terms of HTTP codes (redirects and such).
To answer your core question directly, in the Javascript in the else block where it says that the payment was successfully processed, you can call [0]
location.href = "https://your-success-page.com"
... to send the user to a success page. The reason that the form won't submit is because the submit event of the form has been prevented with ev.preventDefault();
.
This whole flow is documented in detail here [1][2].
Hope this helps!
[0] https://developer.mozilla.org/en-US/docs/Web/API/Window/location
[1] https://stripe.com/docs/payments/accept-a-payment
[2] https://stripe.com/docs/webhooks
Upvotes: 2