# Configurare e distribuire un webhook Learn how to set up and deploy a webhook to listen to events from Stripe. # Interactive webhook endpoint builder Learn how to set up and deploy a webhook endpoint to listen to events from Stripe. Use a webhook endpoint for post-payment commerce events such as sending custom email receipts, fulfilling orders, or updating your database. Do these steps in a sandbox before doing them in live mode. 1. Build the server ~~~ npm install ~~~ 2. Run the server ~~~ npm start ~~~ 1. Run the server ~~~ go run server.go ~~~ 1. Build the server ~~~ pip3 install -r requirements.txt ~~~ 2. Run the server ~~~ export FLASK_APP=server.py python3 -m flask run --port=4242 ~~~ 1. Build the server ~~~ bundle install ~~~ 2. Run the server ~~~ ruby server.rb -o 0.0.0.0 ~~~ 1. Build the server ~~~ composer install ~~~ 2. Run the server ~~~ php -S 127.0.0.1:4242 --docroot=public ~~~ 1. Build the server ~~~ dotnet restore ~~~ 2. Run the server ~~~ dotnet run ~~~ 1. Build the server ~~~ mvn package ~~~ 2. Run the server ~~~ java -cp target/sample-jar-with-dependencies.jar com.stripe.sample.Server ~~~ ~~~ stripe listen --forward-to localhost:4242/webhook.php ~~~ ~~~ stripe listen --forward-to localhost:4242/webhook ~~~ ### Installare la libreria Node di Stripe Installa il pacchetto e importalo nel tuo codice. In alternativa, se inizi da zero e hai bisogno di un file package.json, scarica i file del progetto utilizzando il link Download nell’editor del codice. #### npm Installa la libreria: ```bash npm install --save stripe ``` #### GitHub In alternativa scarica il codice sorgente della libreria stripe-node direttamente [da GitHub](https://github.com/stripe/stripe-node). ### Installare la libreria Ruby di Stripe Installa il ruby gem di Stripe e importalo nel tuo codice. In alternativa, se inizi da zero e hai bisogno di un Gemfile, scarica i file del progetto utilizzando il link Download nell’editor del codice. #### Terminal Installa il gem: ```bash gem install stripe ``` #### Bundler Aggiungi questa riga al Gemfile: ```bash gem 'stripe' ``` #### GitHub In alternativa scarica il codice sorgente della libreria stripe-ruby direttamente [da GitHub](https://github.com/stripe/stripe-ruby). ### Installare la libreria Java di Stripe Aggiungi la dipendenza alla tua build e importa la libreria. In alternativa, se inizi da zero e hai bisogno di un file pom.xml (per Maven), scarica i file del progetto utilizzando il link Download nell’editor del codice. #### Maven Aggiungi la seguente dipendenza al tuo POM e sostituisci {VERSION} con il numero di versione che vuoi utilizzare. ```bash \ncom.stripe\nstripe-java\n{VERSION}\n ``` #### Gradle Aggiungi la dipendenza al tuo file build.gradle e sostituisci {VERSION} con il numero di versione che vuoi utilizzare. ```bash implementation "com.stripe:stripe-java:{VERSION}" ``` #### GitHub Scarica il JAR direttamente [da GitHub](https://github.com/stripe/stripe-java/releases/latest). ### Installare il pacchetto Python di Stripe Installa il pacchetto Stripe e importalo nel tuo codice. In alternativa, se inizi da zero e hai bisogno di un file requirements.txt, scarica i file del progetto utilizzando il link Download nell’editor del codice. #### pip Installa il pacchetto tramite pip: ```bash pip3 install stripe ``` #### GitHub Scarica il codice sorgente della libreria stripe-python direttamente [da GitHub](https://github.com/stripe/stripe-python). ### Installare la libreria PHP di Stripe Installa la libreria con composer e inizializzala con la tua chiave API privata. In alternativa, se inizi da zero e hai bisogno di un file composer.json, scarica i file utilizzando il link Download nell’editor del codice. #### Composer Installa la libreria: ```bash composer require stripe/stripe-php ``` #### GitHub In alternativa scarica il codice sorgente della libreria stripe-php direttamente [da GitHub](https://github.com/stripe/stripe-php). ### Configurare il server Aggiungi la dipendenza alla tua build e importa la libreria. In alternativa, se inizi da zero e hai bisogno di un file go.mod, scarica i file del progetto utilizzando il link Download nell’editor del codice. #### Go Assicurati di eseguire l’inizializzazione con Go Modules: ```bash go get -u github.com/stripe/stripe-go/v85 ``` #### GitHub In alternativa scarica il codice sorgente della libreria stripe-go direttamente [da GitHub](https://github.com/stripe/stripe-go). ### Installare la libreria Stripe.net Installa il pacchetto con dotnet o NuGet. In alternativa, se inizi da zero, scarica i file contenenti un file .csproj configurato. #### dotnet Installa la libreria: ```bash dotnet add package Stripe.net ``` #### NuGet Installa la libreria: ```bash Install-Package Stripe.net ``` #### GitHub In alternativa scarica il codice sorgente della libreria Stripe.net direttamente [da GitHub](https://github.com/stripe/stripe-dotnet). ### Installare le librerie Stripe Installa i pacchetti e importali nel tuo codice. In alternativa, se inizi da zero e hai bisogno di un file `package.json`, scarica i file del progetto utilizzando il link nell’editor del codice. Installa le librerie: ```bash npm install --save stripe @stripe/stripe-js next ``` ### Creare un nuovo endpoint A [webhook endpoint](https://docs.stripe.com/webhooks.md) is a destination on your server that receives requests from Stripe, notifying you about events that happen on your account such as a customer disputing a charge or a successful recurring payment. Add a new endpoint to your server and make sure it’s publicly accessible so we can send unauthenticated POST requests. ### Leggere i dati dell’evento Stripe sends the event data in the request body. Each event is structured as an [Event object](https://docs.stripe.com/api/events.md) with a `type`, `id`, and related Stripe resource nested under `data`. ### Gestire l’evento As soon as you have the event object, check the [type](https://docs.stripe.com/api/events/types.md) to know what kind of event happened. You can use one webhook to handle several different event types at once, or set up individual endpoints for specific events. ### Restituire una risposta 200 [Send a successful 200 response](https://docs.stripe.com/webhooks.md#handle-events-asynchronously) to Stripe as quickly as possible because Stripe retries the event if a response isn’t sent within a reasonable time. Write any long-running processes as code that can run asynchronously outside the webhook endpoint. ### Eseguire il server Build and run your server to test the endpoint at `http://localhost:4242/webhook`. ```bash npm start ``` ### Eseguire il server Build and run your server to test the endpoint at `http://localhost:4242/webhook`. ```bash ruby server.rb ``` ### Eseguire il server Build and run your server to test the endpoint at `http://localhost:4242/webhook`. ```bash python3 -m flask --app server run --port=4242 ``` ### Eseguire il server Build and run your server to test the endpoint at `http://localhost:4242/public/webhook.php`. ```bash php -S 127.0.0.1:4242 ``` ### Eseguire il server Build and run your server to test the endpoint at `http://localhost:4242/webhook`. ```bash dotnet run ``` ### Eseguire il server Build and run your server to test the endpoint at `http://localhost:4242/webhook`. ```bash go run server.go ``` ### Eseguire il server Crea ed esegui il tuo server per testare l’endpoint su http://localhost:4242/webhook. ```bash java -cp target/sample-jar-with-dependencies.jar com.stripe.sample.Server ``` ### Scaricare la CLI Use the Stripe CLI to test your webhook locally. [Download the CLI](https://docs.stripe.com/stripe-cli.md) and log in with your Stripe account. Alternatively, use a service like ngrok to make your local endpoint publicly accessible. ```bash stripe login ``` ### Inoltrare gli eventi sul webhook Set up [event forwarding](https://docs.stripe.com/webhooks.md#test-webhook) with the CLI to send all Stripe events in a sandbox to your local webhook endpoint. ```bash stripe listen --forward-to localhost:4242/webhook ``` ### Inoltrare gli eventi sul webhook Set up [event forwarding](https://docs.stripe.com/webhooks.md#test-webhook) with the CLI to send all Stripe events in testmode to your local webhook endpoint. ```bash stripe listen --forward-to localhost:4242/public/webhook.php ``` ### Simulare gli eventi Use the CLI to [simulate specific events](https://docs.stripe.com/cli/trigger) that test your webhook application logic by sending a POST request to your webhook endpoint with a mocked Stripe event object. ```bash stripe trigger payment_intent.succeeded ``` ### Proteggere il webhook Verify the source of a webhook request to prevent bad actors from sending fake payloads or injecting SQL that modify your backend systems. Secure your webhook with a client signature to validate that Stripe generated a webhook request and that it didn’t come from a server acting like Stripe. ### Add the endpoint signing secret Each webhook endpoint has a unique signing secret, which you can find in the [Webhooks](https://dashboard.stripe.com/workbench/webhooks) tab in Workbench. If you’re testing locally with the Stripe CLI, you can also get the signing secret from the CLI output using the command `stripe listen`. ### Verificare l’evento Use the Stripe library to verify and construct the event from Stripe. You need the endpoint secret, the request headers, and the raw request body to properly verify the event. Alternatively, you can [manually verify](https://docs.stripe.com/webhooks.md?verify=verify-manually#verify-manually) the signature without having to use the Stripe library. ### Leggere la firma della richiesta Each request from Stripe contains a `Stripe-Signature` header. Store a reference to this header value for later use. ### Verificare la richiesta Use the Stripe library to verify that the request came from Stripe. Pass the raw request body, `Stripe-Signature` header, and endpoint secret to construct an [Event](https://docs.stripe.com/api/events/object.md). ### Gestire gli errori Checking for errors helps catch improperly configured webhooks or malformed requests from non-Stripe services. Common errors include using the wrong endpoint secret, passing a parsed representation (for example, JSON) of the request body, or reading the wrong request header. ### Testare l’endpoint Test your secured endpoint by using the Stripe CLI, which sends the proper signature header in each test event. // This is a public sample test API key. // Don’t submit any personally identifiable information in requests made with this key. // Sign in to see your own test API key embedded in code samples. // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. const stripe = require('stripe')('<>'); // Replace this endpoint secret with your endpoint's unique secret // If you are testing with the CLI, find the secret by running 'stripe listen' // If you are using an endpoint defined with the API or dashboard, look in your webhook settings // at https://dashboard.stripe.com/webhooks const endpointSecret = 'whsec_...'; const express = require('express'); const app = express(); app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => { let event = request.body; // Only verify the event if you have an endpoint secret defined. // Otherwise use the basic event deserialized with JSON.parse if (endpointSecret) { // Get the signature sent by Stripe const signature = request.headers['stripe-signature']; try { event = stripe.webhooks.constructEvent( request.body, signature, endpointSecret ); } catch (err) { console.log(`⚠️ Webhook signature verification failed.`, err.message); return response.sendStatus(400); } } // Handle the event switch (event.type) { case 'payment_intent.succeeded': const paymentIntent = event.data.object; console.log(`PaymentIntent for ${paymentIntent.amount} was successful!`); // Then define and call a method to handle the successful payment intent. // handlePaymentIntentSucceeded(paymentIntent); break; case 'payment_method.attached': const paymentMethod = event.data.object; // Then define and call a method to handle the successful attachment of a PaymentMethod. // handlePaymentMethodAttached(paymentMethod); break; default: // Unexpected event type console.log(`Unhandled event type ${event.type}.`); } // Return a 200 response to acknowledge receipt of the event response.send(); app.listen(4242, () => console.log('Running on port 4242')); { "name": "stripe-sample", "version": "1.0.0", "description": "A sample Stripe implementation", "main": "server.js", "scripts": { "start": "node server.js" }, "author": "stripe-samples", "license": "ISC", "dependencies": { "express": "^4.17.1", "stripe": "^21.0.1" } } { "name": "stripe-sample", "version": "0.1.0", "dependencies": { "@stripe/react-stripe-js": "^3.7.0", "@stripe/stripe-js": "^7.3.0", "express": "^4.17.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "^3.4.0", "stripe": "21.0.1" }, "devDependencies": { "concurrently": "4.1.2" }, "homepage": "http://localhost:3000/checkout", "proxy": "http://localhost:4242", "scripts": { "start-client": "react-scripts start", "start-server": "node server.js", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "start": "concurrently \"yarn start-client\" \"yarn start-server\"" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } } require 'stripe' \# This is a public sample test API key. # Don’t submit any personally identifiable information in requests made with this key. # Sign in to see your own test API key embedded in code samples. \# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = Stripe::StripeClient.new('<>') \# Replace this endpoint secret with your endpoint's unique secret # If you are testing with the CLI, find the secret by running 'stripe listen' # If you are using an endpoint defined with the API or dashboard, look in your webhook settings # at https://dashboard.stripe.com/webhooks endpoint_secret = 'whsec_...'; post '/webhook' do payload = request.body.read event = nil begin event = Stripe::Event.construct_from( JSON.parse(payload, symbolize_names: true) ) rescue JSON::ParserError => e \# Invalid payload puts "⚠️ Webhook error while parsing basic request. #{e.message}" status 400 return end \# Check if webhook signing is configured. if endpoint_secret # Retrieve the event by verifying the signature using the raw body and secret. signature = request.env['HTTP_STRIPE_SIGNATURE']; begin event = Stripe::Webhook.construct_event( payload, signature, endpoint_secret ) rescue Stripe::SignatureVerificationError => e puts "⚠️ Webhook signature verification failed. #{e.message}" status 400 end end \# Handle the event case event.type when 'payment_intent.succeeded' payment_intent = event.data.object # contains a Stripe::PaymentIntent puts "Payment for #{payment_intent['amount']} succeeded." # Then define and call a method to handle the successful payment intent. # handle_payment_intent_succeeded(payment_intent) when 'payment_method.attached' payment_method = event.data.object # contains a Stripe::PaymentMethod # Then define and call a method to handle the successful attachment of a PaymentMethod. # handle_payment_method_attached(payment_method) else puts "Unhandled event type: #{event.type}" end status 200 import stripe \# This is a public sample test API key. # Don’t submit any personally identifiable information in requests made with this key. # Sign in to see your own test API key embedded in code samples. \# Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. client = stripe.StripeClient('<>') \# Replace this endpoint secret with your endpoint's unique secret # If you are testing with the CLI, find the secret by running 'stripe listen' # If you are using an endpoint defined with the API or dashboard, look in your webhook settings # at https://dashboard.stripe.com/webhooks endpoint_secret = 'whsec_...' app = Flask(__name__) @app.route('/webhook', methods=['POST']) try: event = json.loads(payload) except json.decoder.JSONDecodeError as e: print('⚠️ Webhook error while parsing basic request.' + str(e)) return jsonify(success=False) if endpoint_secret: \# Only verify the event if there is an endpoint secret defined # Otherwise use the basic event deserialized with json sig_header = request.headers.get('stripe-signature') try: event = client.construct_event( payload, sig_header, endpoint_secret ) except stripe.error.SignatureVerificationError as e: print('⚠️ Webhook signature verification failed.' + str(e)) return jsonify(success=False) \# Handle the event if event and event['type'] == 'payment_intent.succeeded': payment_intent = event['data']['object'] # contains a stripe.PaymentIntent print('Payment for {} succeeded'.format(payment_intent['amount'])) # Then define and call a method to handle the successful payment intent. # handle_payment_intent_succeeded(payment_intent) elif event['type'] == 'payment_method.attached': payment_method = event['data']['object'] # contains a stripe.PaymentMethod # Then define and call a method to handle the successful attachment of a PaymentMethod. # handle_payment_method_attached(payment_method) else: # Unexpected event type print('Unhandled event type {}'.format(event['type'])) return jsonify(success=True) certifi==2026.1.4 chardet==5.2.0 click==8.3.1 Flask==3.1.2 idna==3.11 itsdangerous==2.2.0 Jinja2==3.1.6 MarkupSafe==3.0.3 requests==2.32.5 stripe==15.0.0 toml==0.10.2 Werkzeug==3.1.5 $stripe = new \Stripe\StripeClient($stripeSecretKey); // Replace this endpoint secret with your endpoint's unique secret // If you are testing with the CLI, find the secret by running 'stripe listen' // If you are using an endpoint defined with the API or dashboard, look in your webhook settings // at https://dashboard.stripe.com/webhooks $endpoint_secret = 'whsec_...'; $payload = @file_get_contents('php://input'); $event = null; try { $event = \Stripe\Event::constructFrom( json_decode($payload, true) ); } catch(\UnexpectedValueException $e) { // Invalid payload echo '⚠️ Webhook error while parsing basic request.'; http_response_code(400); exit(); } if ($endpoint_secret) { // Only verify the event if there is an endpoint secret defined // Otherwise use the basic decoded event $sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE']; try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $endpoint_secret ); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid signature echo '⚠️ Webhook error while validating signature.'; http_response_code(400); exit(); } } // Handle the event switch ($event->type) { case 'payment_intent.succeeded': $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent // Then define and call a method to handle the successful payment intent. // handlePaymentIntentSucceeded($paymentIntent); break; case 'payment_method.attached': $paymentMethod = $event->data->object; // contains a \Stripe\PaymentMethod // Then define and call a method to handle the successful attachment of a PaymentMethod. // handlePaymentMethodAttached($paymentMethod); break; default: // Unexpected event type error_log('Received unknown event type'); } http_response_code(200); // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. $stripeSecretKey = '<>'; // This is a public sample test API key. // Don’t submit any personally identifiable information in requests made with this key. // Sign in to see your own test API key embedded in code samples. // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. services.AddSingleton(new StripeClient("<>")); [Route("webhook")] [ApiController] public class WebhookController : Controller const string endpointSecret = "whsec_..."; var stripeEvent = EventUtility.ParseEvent(json); var signatureHeader = Request.Headers["Stripe-Signature"]; stripeEvent = EventUtility.ConstructEvent(json, signatureHeader, endpointSecret); // If on SDK version < 46, use class Events instead of EventTypes if (stripeEvent.Type == EventTypes.PaymentIntentSucceeded) { var paymentIntent = stripeEvent.Data.Object as PaymentIntent; Console.WriteLine("A successful payment for {0} was made.", paymentIntent.Amount); // Then define and call a method to handle the successful payment intent. // handlePaymentIntentSucceeded(paymentIntent); } else if (stripeEvent.Type == EventTypes.PaymentMethodAttached) { var paymentMethod = stripeEvent.Data.Object as PaymentMethod; // Then define and call a method to handle the successful attachment of a PaymentMethod. // handlePaymentMethodAttached(paymentMethod); } else { Console.WriteLine("Unhandled event type: {0}", stripeEvent.Type); } return Ok(); catch (StripeException e) { Console.WriteLine("Error: {0}", e.Message); return BadRequest(); } "github.com/stripe/stripe-go/v85" "github.com/stripe/stripe-go/v85/webhook" // This is a public sample test API key. // Don’t submit any personally identifiable information in requests made with this key. // Sign in to see your own test API key embedded in code samples. // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. sc = stripe.NewClient("<>") http.HandleFunc("/webhook", handleWebhook) event := stripe.Event{} if err := json.Unmarshal(payload, &event); err != nil { fmt.Fprintf(os.Stderr, "⚠️ Webhook error while parsing basic request. %v\n", err.Error()) w.WriteHeader(http.StatusBadRequest) return } // Replace this endpoint secret with your endpoint's unique secret // If you are testing with the CLI, find the secret by running 'stripe listen' // If you are using an endpoint defined with the API or dashboard, look in your webhook settings // at https://dashboard.stripe.com/webhooks endpointSecret := "whsec_..." signatureHeader := req.Header.Get("Stripe-Signature") event, err = sc.ConstructEvent(payload, signatureHeader, endpointSecret) if err != nil { fmt.Fprintf(os.Stderr, "⚠️ Webhook signature verification failed. %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature return } // Unmarshal the event data into an appropriate struct depending on its Type switch event.Type { case "payment_intent.succeeded": var paymentIntent stripe.PaymentIntent err := json.Unmarshal(event.Data.Raw, &paymentIntent) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } log.Printf("Successful payment for %d.", paymentIntent.Amount) // Then define and call a func to handle the successful payment intent. // handlePaymentIntentSucceeded(paymentIntent) case "payment_method.attached": var paymentMethod stripe.PaymentMethod err := json.Unmarshal(event.Data.Raw, &paymentMethod) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } // Then define and call a func to handle the successful attachment of a PaymentMethod. // handlePaymentMethodAttached(paymentMethod) default: fmt.Fprintf(os.Stderr, "Unhandled event type: %s\n", event.Type) } w.WriteHeader(http.StatusOK) require github.com/stripe/stripe-go/v85 v85.0.0 // This is a public sample test API key. // Don’t submit any personally identifiable information in requests made with this key. // Sign in to see your own test API key embedded in code samples. // Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. StripeClient client = new StripeClient("<>"); // Replace this endpoint secret with your endpoint's unique secret // If you are testing with the CLI, find the secret by running 'stripe listen' // If you are using an endpoint defined with the API or dashboard, look in your webhook settings // at https://dashboard.stripe.com/webhooks String endpointSecret = "whsec_..."; post("/webhook", (request, response) -> { String payload = request.body(); Event event = null; try { event = ApiResource.GSON.fromJson(payload, Event.class); } catch (JsonSyntaxException e) { // Invalid payload System.out.println("⚠️ Webhook error while parsing basic request."); response.status(400); return ""; } String sigHeader = request.headers("Stripe-Signature"); if(endpointSecret != null && sigHeader != null) { // Only verify the event if you have an endpoint secret defined. // Otherwise use the basic event deserialized with GSON. try { event = client.constructEvent( payload, sigHeader, endpointSecret ); } catch (SignatureVerificationException e) { // Invalid signature System.out.println("⚠️ Webhook error while validating signature."); response.status(400); return ""; } } // Handle the event switch (event.getType()) { case "payment_intent.succeeded": PaymentIntent paymentIntent = (PaymentIntent) stripeObject; System.out.println("Payment for " + paymentIntent.getAmount() + " succeeded."); // Then define and call a method to handle the successful payment intent. // handlePaymentIntentSucceeded(paymentIntent); break; case "payment_method.attached": PaymentMethod paymentMethod = (PaymentMethod) stripeObject; // Then define and call a method to handle the successful attachment of a PaymentMethod. // handlePaymentMethodAttached(paymentMethod); break; default: System.out.println("Unhandled event type: " + event.getType()); break; } response.status(200); return ""; ## Passaggi successivi #### [Secure your webhooks](https://docs.stripe.com/webhooks.md#verify-events) Secure your webhook endpoint by allowing only verified events from Stripe. #### [Going live](https://docs.stripe.com/webhooks.md#register-webhook) Scopri come distribuire l’endpoint del webhook nell’ambiente di produzione e gestire gli eventi su larga scala inviando solo gli eventi specifici di cui hai bisogno. #### [Best practices](https://docs.stripe.com/webhooks.md#best-practices) Comprendi le pratiche ottimali l’endpoint, ad esempio la gestione dei tentativi o degli eventi duplicati. #### [Stripe CLI](https://docs.stripe.com/stripe-cli.md) La CLI di Stripe dispone di numerosi comandi che ti consentono di testare l’applicazione Stripe oltre ai webhook.