Connect
Listen for updates

Connect webhooks

Learn how to use webhooks with Connect to be notified of Stripe activity.

Stripe uses webhooks to notify your application when an event happens in your account. All Connect integrations should establish a webhook endpoint to listen for Connect events.

There are several events related to accounts that Stripe recommends listening for:

Event Description
account.application.deauthorized Occurs when a user disconnects from your account and can be used to trigger required cleanup on your server. Available for Standard accounts.
account.updated Allows you to monitor changes to connected account requirements and status changes. Available for Standard, Express, and Custom accounts.
person.updated If you use the Persons API, allows you to monitor changes to requirements and status changes for individuals. Available for Express and Custom accounts.
payment_intent.succeeded Occurs when a payment intent results in a successful charge. Available for all payments, including destination and direct charges
balance.available Occurs when your Stripe balance has been updated (e.g., when funds you've added from your bank account are available for transfer to your connected account).
account.external_account.updated Occurs when a bank account or debit card attached to a connected account is updated, which can impact payouts. Available for Express and Custom accounts.
payout.failed Occurs when a payout fails. When a payout fails, the external account involved will be disabled, and no automatic or manual payouts can go through until the external account is updated. Available for Express and Custom accounts.
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'account.application.deauthorized' application = event['data']['object'] connected_account_id = event['account'] handle_deauthorization(connected_account_id, application) end status 200 end def handle_deauthorization(connected_account_id, application) # Fulfill the purchase. puts 'Connected account ID: ' + connected_account_id puts application.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "account.application.deauthorized": application = event["data"]["object"] connected_account_id = event["account"] handle_deauthorization(connected_account_id, application) return json.dumps({"success": True}), 200 def handle_deauthorization(connected_account_id, application): # Fulfill the purchase. print('Connected account ID: ' + connected_account_id) print(str( application)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'account.application.deauthorized') { $application = $event->data->object; $connectedAccountId = $event->account; handleDeauthorization($connectedAccountId, $application); } return $response->withStatus(200); }); function handleDeauthorization($connectedAccountId, $application) { // Fulfill the purchase. echo 'Connected account ID: ' . $connectedAccountId; echo $application; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'account.application.deauthorized') { const application = event.data.object; const connectedAccountId = event.account; handleDeauthorization(connectedAccountId, application); } response.json({received: true}); }); const handleDeauthorization = (connectedAccountId, application) => { // Fulfill the purchase. console.log('Connected account ID: ' + connectedAccountId); console.log(JSON.stringify(application)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.Application; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("account.application.deauthorized".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); Application application = null; if (dataObjectDeserializer.getObject().isPresent()) { application = (Application) dataObjectDeserializer.getObject().get(); String connectedAccountId = event.getAccount(); handleDeauthorization(connectedAccountId, application); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handleDeauthorization(String connectedAccountId, Application application) { // Fulfill the purchase. System.out.println("Connected account ID: " + connectedAccountId); System.out.println(application.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "account.application.deauthorized" { var application stripe.Application err := json.Unmarshal(event.Data.Raw, &application) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } var connectedAccountId = event.Account; handleDeauthorization(connectedAccountId, application) } w.WriteHeader(http.StatusOK) } func handleDeauthorization(connectedAccountId string, application stripe.Application) { // Fulfill the purchase. log.Println("Connected account ID: " + connectedAccountId) log.Println(application.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.AccountApplicationDeauthorized) { var application = stripeEvent.Data.Object as Application; var connectedAccountId = stripeEvent.Account; HandleDeauthorization(connectedAccountId, application); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } private void HandleDeauthorization(string connectedAccountId, Application application) { // Fulfill the purchase. logger.LogInformation($"Connected account ID: {connectedAccountId}"); logger.LogInformation($"{application}"); } } }
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'account.updated' account = event['data']['object'] handle_account_update(account) end status 200 end def handle_account_update(account) # Fulfill the purchase. puts account.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "account.updated": account = event["data"]["object"] handle_account_update(account) return json.dumps({"success": True}), 200 def handle_account_update(account): # Fulfill the purchase. print(str( account)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'account.updated') { $account = $event->data->object; handleAccountUpdate($account); } return $response->withStatus(200); }); function handleAccountUpdate($account) { // Fulfill the purchase. echo $account; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'account.updated') { const account = event.data.object; handleAccountUpdate(account); } response.json({received: true}); }); const handleAccountUpdate = (account) => { // Fulfill the purchase. console.log(JSON.stringify(account)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.Account; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("account.updated".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); Account account = null; if (dataObjectDeserializer.getObject().isPresent()) { account = (Account) dataObjectDeserializer.getObject().get(); handleAccountUpdate(account); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handleAccountUpdate(Account account) { // Fulfill the purchase. System.out.println(account.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "account.updated" { var account stripe.Account err := json.Unmarshal(event.Data.Raw, &account) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } handleAccountUpdate(account) } w.WriteHeader(http.StatusOK) } func handleAccountUpdate(account stripe.Account) { // Fulfill the purchase. log.Println(account.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.AccountUpdated) { var account = stripeEvent.Data.Object as Account; HandleAccountUpdate(account); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } // Fulfill the purchase. private void HandleAccountUpdate(Account account) { logger.LogInformation($"{account}"); } } }
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'person.updated' person = event['data']['object'] connected_account_id = event['account'] handle_person_update(connected_account_id, person) end status 200 end def handle_person_update(connected_account_id, person) # Fulfill the purchase. puts 'Connected account ID: ' + connected_account_id puts person.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "person.updated": person = event["data"]["object"] connected_account_id = event["account"] handle_person_update(connected_account_id, person) return json.dumps({"success": True}), 200 def handle_person_update(connected_account_id, person): # Fulfill the purchase. print('Connected account ID: ' + connected_account_id) print(str( person)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'person.updated') { $person = $event->data->object; $connectedAccountId = $event->account; handlePersonUpdate($connectedAccountId, $person); } return $response->withStatus(200); }); function handlePersonUpdate($connectedAccountId, $person) { // Fulfill the purchase. echo 'Connected account ID: ' . $connectedAccountId; echo $person; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'person.updated') { const person = event.data.object; const connectedAccountId = event.account; handlePersonUpdate(connectedAccountId, person); } response.json({received: true}); }); const handlePersonUpdate = (connectedAccountId, person) => { // Fulfill the purchase. console.log('Connected account ID: ' + connectedAccountId); console.log(JSON.stringify(person)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.Person; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("person.updated".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); Person person = null; if (dataObjectDeserializer.getObject().isPresent()) { person = (Person) dataObjectDeserializer.getObject().get(); String connectedAccountId = event.getAccount(); handlePersonUpdate(connectedAccountId, person); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handlePersonUpdate(String connectedAccountId, Person person) { // Fulfill the purchase. System.out.println("Connected account ID: " + connectedAccountId); System.out.println(person.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "person.updated" { var person stripe.Person err := json.Unmarshal(event.Data.Raw, &person) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } var connectedAccountId = event.Account; handlePersonUpdate(connectedAccountId, person) } w.WriteHeader(http.StatusOK) } func handlePersonUpdate(connectedAccountId string, person stripe.Person) { // Fulfill the purchase. log.Println("Connected account ID: " + connectedAccountId) log.Println(person.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.PersonUpdated) { var person = stripeEvent.Data.Object as Person; var connectedAccountId = stripeEvent.Account; HandlePersonUpdate(connectedAccountId, person); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } private void HandlePersonUpdate(string connectedAccountId, Person person) { // Fulfill the purchase. logger.LogInformation($"Connected account ID: {connectedAccountId}"); logger.LogInformation($"{person}"); } } }
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'payment_intent.succeeded' payment_intent = event['data']['object'] connected_account_id = event['account'] handle_successful_payment_intent(connected_account_id, payment_intent) end status 200 end def handle_successful_payment_intent(connected_account_id, payment_intent) # Fulfill the purchase. puts 'Connected account ID: ' + connected_account_id puts payment_intent.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "payment_intent.succeeded": payment_intent = event["data"]["object"] connected_account_id = event["account"] handle_successful_payment_intent(connected_account_id, payment_intent) return json.dumps({"success": True}), 200 def handle_successful_payment_intent(connected_account_id, payment_intent): # Fulfill the purchase. print('Connected account ID: ' + connected_account_id) print(str( payment_intent)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'payment_intent.succeeded') { $paymentIntent = $event->data->object; $connectedAccountId = $event->account; handleSuccessfulPaymentIntent($connectedAccountId, $paymentIntent); } return $response->withStatus(200); }); function handleSuccessfulPaymentIntent($connectedAccountId, $paymentIntent) { // Fulfill the purchase. echo 'Connected account ID: ' . $connectedAccountId; echo $paymentIntent; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'payment_intent.succeeded') { const paymentIntent = event.data.object; const connectedAccountId = event.account; handleSuccessfulPaymentIntent(connectedAccountId, paymentIntent); } response.json({received: true}); }); const handleSuccessfulPaymentIntent = (connectedAccountId, paymentIntent) => { // Fulfill the purchase. console.log('Connected account ID: ' + connectedAccountId); console.log(JSON.stringify(paymentIntent)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.PaymentIntent; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("payment_intent.succeeded".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); PaymentIntent paymentIntent = null; if (dataObjectDeserializer.getObject().isPresent()) { paymentIntent = (PaymentIntent) dataObjectDeserializer.getObject().get(); String connectedAccountId = event.getAccount(); handleSuccessfulPaymentIntent(connectedAccountId, paymentIntent); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handleSuccessfulPaymentIntent(String connectedAccountId, PaymentIntent paymentIntent) { // Fulfill the purchase. System.out.println("Connected account ID: " + connectedAccountId); System.out.println(paymentIntent.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "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 } var connectedAccountId = event.Account; handleSuccessfulPaymentIntent(connectedAccountId, paymentIntent) } w.WriteHeader(http.StatusOK) } func handleSuccessfulPaymentIntent(connectedAccountId string, paymentIntent stripe.PaymentIntent) { // Fulfill the purchase. log.Println("Connected account ID: " + connectedAccountId) log.Println(paymentIntent.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.PaymentIntentSucceeded) { var paymentIntent = stripeEvent.Data.Object as PaymentIntent; var connectedAccountId = stripeEvent.Account; HandleSuccessfulPaymentIntent(connectedAccountId, paymentIntent); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } private void HandleSuccessfulPaymentIntent(string connectedAccountId, PaymentIntent paymentIntent) { // Fulfill the purchase. logger.LogInformation($"Connected account ID: {connectedAccountId}"); logger.LogInformation($"{paymentIntent}"); } } }
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'payment_intent.succeeded' payment_intent = event['data']['object'] handle_successful_payment_intent(payment_intent) end status 200 end def handle_successful_payment_intent(payment_intent) # Fulfill the purchase. puts payment_intent.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "payment_intent.succeeded": payment_intent = event["data"]["object"] handle_successful_payment_intent(payment_intent) return json.dumps({"success": True}), 200 def handle_successful_payment_intent(payment_intent): # Fulfill the purchase. print(str( payment_intent)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'payment_intent.succeeded') { $paymentIntent = $event->data->object; handleSuccessfulPaymentIntent($paymentIntent); } return $response->withStatus(200); }); function handleSuccessfulPaymentIntent($paymentIntent) { // Fulfill the purchase. echo $paymentIntent; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'payment_intent.succeeded') { const paymentIntent = event.data.object; handleSuccessfulPaymentIntent(paymentIntent); } response.json({received: true}); }); const handleSuccessfulPaymentIntent = (paymentIntent) => { // Fulfill the purchase. console.log(JSON.stringify(paymentIntent)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.PaymentIntent; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("payment_intent.succeeded".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); PaymentIntent paymentIntent = null; if (dataObjectDeserializer.getObject().isPresent()) { paymentIntent = (PaymentIntent) dataObjectDeserializer.getObject().get(); handleSuccessfulPaymentIntent(paymentIntent); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handleSuccessfulPaymentIntent(PaymentIntent paymentIntent) { // Fulfill the purchase. System.out.println(paymentIntent.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "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 } handleSuccessfulPaymentIntent(paymentIntent) } w.WriteHeader(http.StatusOK) } func handleSuccessfulPaymentIntent(paymentIntent stripe.PaymentIntent) { // Fulfill the purchase. log.Println(paymentIntent.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.PaymentIntentSucceeded) { var paymentIntent = stripeEvent.Data.Object as PaymentIntent; HandleSuccessfulPaymentIntent(paymentIntent); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } // Fulfill the purchase. private void HandleSuccessfulPaymentIntent(PaymentIntent paymentIntent) { logger.LogInformation($"{paymentIntent}"); } } }
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'balance.available' balance = event['data']['object'] handle_available_balance(balance) end status 200 end def handle_available_balance(balance) # Fulfill the purchase. puts balance.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "balance.available": balance = event["data"]["object"] handle_available_balance(balance) return json.dumps({"success": True}), 200 def handle_available_balance(balance): # Fulfill the purchase. print(str( balance)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'balance.available') { $balance = $event->data->object; handleAvailableBalance($balance); } return $response->withStatus(200); }); function handleAvailableBalance($balance) { // Fulfill the purchase. echo $balance; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'balance.available') { const balance = event.data.object; handleAvailableBalance(balance); } response.json({received: true}); }); const handleAvailableBalance = (balance) => { // Fulfill the purchase. console.log(JSON.stringify(balance)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.Balance; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("balance.available".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); Balance balance = null; if (dataObjectDeserializer.getObject().isPresent()) { balance = (Balance) dataObjectDeserializer.getObject().get(); handleAvailableBalance(balance); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handleAvailableBalance(Balance balance) { // Fulfill the purchase. System.out.println(balance.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "balance.available" { var balance stripe.Balance err := json.Unmarshal(event.Data.Raw, &balance) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } handleAvailableBalance(balance) } w.WriteHeader(http.StatusOK) } func handleAvailableBalance(balance stripe.Balance) { // Fulfill the purchase. log.Println(balance.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.BalanceAvailable) { var balance = stripeEvent.Data.Object as Balance; HandleAvailableBalance(balance); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } // Fulfill the purchase. private void HandleAvailableBalance(Balance balance) { logger.LogInformation($"{balance}"); } } }
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'account.external_account.updated' external_account = event['data']['object'] connected_account_id = event['account'] handle_external_account_update(connected_account_id, external_account) end status 200 end def handle_external_account_update(connected_account_id, external_account) # Fulfill the purchase. puts 'Connected account ID: ' + connected_account_id puts external_account.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "account.external_account.updated": external_account = event["data"]["object"] connected_account_id = event["account"] handle_external_account_update(connected_account_id, external_account) return json.dumps({"success": True}), 200 def handle_external_account_update(connected_account_id, external_account): # Fulfill the purchase. print('Connected account ID: ' + connected_account_id) print(str( external_account)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'account.external_account.updated') { $externalAccount = $event->data->object; $connectedAccountId = $event->account; handleExternalAccountUpdate($connectedAccountId, $externalAccount); } return $response->withStatus(200); }); function handleExternalAccountUpdate($connectedAccountId, $externalAccount) { // Fulfill the purchase. echo 'Connected account ID: ' . $connectedAccountId; echo $externalAccount; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'account.external_account.updated') { const externalAccount = event.data.object; const connectedAccountId = event.account; handleExternalAccountUpdate(connectedAccountId, externalAccount); } response.json({received: true}); }); const handleExternalAccountUpdate = (connectedAccountId, externalAccount) => { // Fulfill the purchase. console.log('Connected account ID: ' + connectedAccountId); console.log(JSON.stringify(externalAccount)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.ExternalAccount; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("account.external_account.updated".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); ExternalAccount externalAccount = null; if (dataObjectDeserializer.getObject().isPresent()) { externalAccount = (ExternalAccount) dataObjectDeserializer.getObject().get(); String connectedAccountId = event.getAccount(); handleExternalAccountUpdate(connectedAccountId, externalAccount); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handleExternalAccountUpdate(String connectedAccountId, ExternalAccount externalAccount) { // Fulfill the purchase. System.out.println("Connected account ID: " + connectedAccountId); System.out.println(externalAccount.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "account.external_account.updated" { var externalAccount stripe.ExternalAccount err := json.Unmarshal(event.Data.Raw, &externalAccount) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } var connectedAccountId = event.Account; handleExternalAccountUpdate(connectedAccountId, externalAccount) } w.WriteHeader(http.StatusOK) } func handleExternalAccountUpdate(connectedAccountId string, externalAccount stripe.ExternalAccount) { // Fulfill the purchase. log.Println("Connected account ID: " + connectedAccountId) log.Println(externalAccount.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.AccountExternalAccountUpdated) { var externalAccount = stripeEvent.Data.Object as IExternalAccount; var connectedAccountId = stripeEvent.Account; HandleExternalAccountUpdate(connectedAccountId, externalAccount); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } private void HandleExternalAccountUpdate(string connectedAccountId, IExternalAccount externalAccount) { // Fulfill the purchase. logger.LogInformation($"Connected account ID: {connectedAccountId}"); logger.LogInformation($"{externalAccount}"); } } }
# Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, webhook_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'payout.failed' payout = event['data']['object'] connected_account_id = event['account'] handle_failed_payout(connected_account_id, payout) end status 200 end def handle_failed_payout(connected_account_id, payout) # Fulfill the purchase. puts 'Connected account ID: ' + connected_account_id puts payout.to_s end
import stripe import json # Using Flask. from flask import ( Flask, render_template, request, Response, ) app = Flask(__name__, static_folder=".", static_url_path="", template_folder=".") # Set your secret key. Remember to switch to your live secret key in production! # See your keys here: https://dashboard.stripe.com/account/apikeys stripe.api_key = 'sk_test_4eC39HqLyjWDarjtT1zdp7dc' # Uncomment and replace with a real secret. You can find your endpoint's # secret in your webhook settings. # webhook_secret = 'whsec_...' @app.route("/webhook", methods=["POST"]) def webhook_received(): request_data = json.loads(request.data) signature = request.headers.get("stripe-signature") # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks/signatures for more information. try: event = stripe.Webhook.construct_event( payload=request.data, sig_header=signature, secret=webhook_secret ) except ValueError as e: # Invalid payload. return Response(status=400) except stripe.error.SignatureVerificationError as e: # Invalid Signature. return Response(status=400) if event["type"] == "payout.failed": payout = event["data"]["object"] connected_account_id = event["account"] handle_failed_payout(connected_account_id, payout) return json.dumps({"success": True}), 200 def handle_failed_payout(connected_account_id, payout): # Fulfill the purchase. print('Connected account ID: ' + connected_account_id) print(str( payout)) if __name__ == "__main__": app.run(port=4242)
<?php // Using Slim. use Slim\Http\Request; use Slim\Http\Response; use Stripe\Stripe; require_once('vendor/autoload.php'); $app = new \Slim\App; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys \Stripe\Stripe::setApiKey('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // $webhook_secret = 'whsec_...'; $app->post('/webhook', function ($request, $response, $next) { $payload = $request->getBody(); $sig_header = $request->getHeaderLine('stripe-signature'); $event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $webhook_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload. return $response->withStatus(400); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid Signature. return $response->withStatus(400); } if ($event->type == 'payout.failed') { $payout = $event->data->object; $connectedAccountId = $event->account; handleFailedPayout($connectedAccountId, $payout); } return $response->withStatus(200); }); function handleFailedPayout($connectedAccountId, $payout) { // Fulfill the purchase. echo 'Connected account ID: ' . $connectedAccountId; echo $payout; }; $app->run();
// Using Express const express = require('express'); const bodyParser = require("body-parser"); const app = express(); app.use(express.json()); // Use JSON parser for all non-webhook routes app.use((req, res, next) => { if (req.originalUrl === "/webhook") { next(); } else { bodyParser.json()(req, res, next); } }); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc'); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const webhook_secret = 'whsec_...'' app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = stripe.webhooks.constructEvent(request.body, sig, webhook_secret); } catch (err) { return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'payout.failed') { const payout = event.data.object; const connectedAccountId = event.account; handleFailedPayout(connectedAccountId, payout); } response.json({received: true}); }); const handleFailedPayout = (connectedAccountId, payout) => { // Fulfill the purchase. console.log('Connected account ID: ' + connectedAccountId); console.log(JSON.stringify(payout)); } app.listen(4242, () => console.log(`Node server listening on port ${4242}!`));
package com.stripe.sample; import com.stripe.Stripe; import com.stripe.model.Payout; import com.stripe.model.Event; import com.stripe.model.EventDataObjectDeserializer; import com.stripe.exception.SignatureVerificationException; import com.stripe.net.Webhook; import com.google.gson.JsonSyntaxException; import spark.Response; // Using Spark. import static spark.Spark.*; public class Server { public static void main(String[] args) { port(4242); // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys Stripe.apiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; post("/webhook", (request, response) -> { String payload = request.body(); String sigHeader = request.headers("Stripe-Signature"); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // String webhookSecret = "whsec_..." Event event = null; // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { event = Webhook.constructEvent( payload, sigHeader, webhookSecret ); } catch (JsonSyntaxException e) { // Invalid payload. response.status(400); return ""; } catch (SignatureVerificationException e) { // Invalid Signature. response.status(400); return ""; } if ("payout.failed".equals(event.getType())) { // Deserialize the nested object inside the event EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer(); Payout payout = null; if (dataObjectDeserializer.getObject().isPresent()) { payout = (Payout) dataObjectDeserializer.getObject().get(); String connectedAccountId = event.getAccount(); handleFailedPayout(connectedAccountId, payout); } else { // Deserialization failed, probably due to an API version mismatch. // Refer to the Javadoc documentation on `EventDataObjectDeserializer` for // instructions on how to handle this case, or return an error here. } } response.status(200); return ""; }); } private static void handleFailedPayout(String connectedAccountId, Payout payout) { // Fulfill the purchase. System.out.println("Connected account ID: " + connectedAccountId); System.out.println(payout.getId()); } }
package main import ( "encoding/json" "log" "fmt" "net/http" "io/ioutil" "github.com/stripe/stripe-go/v71" "github.com/stripe/stripe-go/v71/webhook" "os" ) func main() { // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys stripe.Key = "sk_test_4eC39HqLyjWDarjtT1zdp7dc" http.HandleFunc("/webhook", handleWebhook) addr := "localhost:4242" log.Printf("Listening on %s ...", addr) log.Fatal(http.ListenAndServe(addr, nil)) } func handleWebhook(w http.ResponseWriter, req *http.Request) { const MaxBodyBytes = int64(65536) req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes) body, err := ioutil.ReadAll(req.Body) if err != nil { fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err) w.WriteHeader(http.StatusServiceUnavailable) return } // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // webhookSecret := "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. event, err := webhook.ConstructEvent(body, req.Header.Get("Stripe-Signature"), webhookSecret) if err != nil { fmt.Fprintf(os.Stderr, "Error verifying webhook signature: %v\n", err) w.WriteHeader(http.StatusBadRequest) // Return a 400 error on a bad signature. return } if event.Type == "payout.failed" { var payout stripe.Payout err := json.Unmarshal(event.Data.Raw, &payout) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err) w.WriteHeader(http.StatusBadRequest) return } var connectedAccountId = event.Account; handleFailedPayout(connectedAccountId, payout) } w.WriteHeader(http.StatusOK) } func handleFailedPayout(connectedAccountId string, payout stripe.Payout) { // Fulfill the purchase. log.Println("Connected account ID: " + connectedAccountId) log.Println(payout.ID) }
// Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; using System; using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Stripe; namespace Controllers { public class ConnectController : Controller { private readonly ILogger<ConnectController> logger; public ConnectController( ILogger<ConnectController> logger, ) { this.logger = logger; } [HttpPost("webhook")] public async Task<IActionResult> ProcessWebhookEvent() { var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(); // Uncomment and replace with a real secret. You can find your endpoint's // secret in your webhook settings. // const string webhookSecret = "whsec_..." // Verify webhook signature and extract the event. // See https://stripe.com/docs/webhooks/signatures for more information. try { var stripeEvent = EventUtility.ConstructEvent(json, Request.Headers["Stripe-Signature"], webhookSecret); if (stripeEvent.Type == Events.PayoutUpdated) { var payout = stripeEvent.Data.Object as Payout; var connectedAccountId = stripeEvent.Account; HandleFailedPayout(connectedAccountId, payout); } return Ok(); } catch (Exception e) { logger.LogInformation(e.ToString()); return BadRequest(); } } private void HandleFailedPayout(string connectedAccountId, Payout payout) { // Fulfill the purchase. logger.LogInformation($"Connected account ID: {connectedAccountId}"); logger.LogInformation($"{payout}"); } } }

The events listed above are the ones we typically recommend Connect integrations listen for, but there are many other event types you may be interested in.

Connect webhooks

There are a few types of webhooks:

  • Account webhooks are for activity on your own account (e.g., most requests made using your API keys and without authenticating as another Stripe account). This includes all types of charges, except those made directly on a connected account.
  • Connect webhooks are for activity on any connected account. This includes the important account.updated event for any connected account and direct charges.

When creating your webhook, ensure it is correctly configured to receive Connect webhook events. You can do this with the API by setting the connect parameter to true when creating the webhook endpoint, or through the Dashboard.

For Connect webhooks, it’s important to note that while only test webhooks will be sent to your development webhook URLs, both live and test webhooks will be sent to your production webhook URLs. This is due to the fact that you can perform both live and test transactions under a production application. For this reason, we recommend you check the livemode value when receiving an event webhook to know what action, if any, should be taken.

In addition to the documented response properties in the event object reference, each event for a connected account will also contain a top-level account property. It identifies the user for whom the webhook is being sent.

{ "id": "evt_E2m3OgqYC5IlQm", "livemode": true, "object": "event", "type": "customer.created", "account": "acct_fV1gCM4ANDn4zA", "pending_webhooks": 2, "created": 1349654313, "data": {...} }

Test webhooks locally

You can test webhooks locally with the Stripe CLI.

  1. If you haven’t already, install the Stripe CLI on your machine.

  2. Log in to your Stripe account and set up the CLI by running stripe login on the command line.

  3. Allow your local host to receive a simulated event on your connected account by running stripe listen --forward-to localhost:{PORT}/webhook in one terminal window, and running stripe trigger {{EVENT_NAME}} in another.

See also