Testing the Stripe workflow can be done by using a mock framework for your programming language. For instance stripe-ruby-mock offers mocking capabilities for the official Ruby Stripe binding stripe-ruby. If you need bindings for other languages, make sure to check out the API Libraries section in the Stripe documentation.
If however you need to run end-to-end tests of Stripe Webhooks against your development environment you will surely run into problems as that requires your development server to be publicly accessible on the internet, which is usually not the case.
As described in the Testing section of the Stripe documentation, one option is to simply capture the rebhook request for inspection by using a service such as RequestBin. This will however not enable you to run tests end-to-end.
Reverse SSH tunneling (remote port forwarding)
The concept of an SSH tunnel is a powerful one. It allows us to channel traffic through an intermediate host accessible via the SSH protocol. SSH tunneling (also referred to as port forwarding) can be achieved in two directions. Either by forwarding a local port to a remote host/port, called
local port forwarding, or by forwarding a remote host/port to a local port, called
remote port forwarding.
remote port forwarding is what allows us to open up a port on a publicly available machine, e.g. an Amazon EC2 instance and forward incoming traffic back to our development machine sitting behind a firewall.
One inherent awesomeness with this approach is that all traffic going through the tunnel is encrypted.
Establishing a reverse SSH tunnel
Establishing a reverse tunnel is possible by passing the
-R flag to SSH when connecting to the remote host. Imagine we have a local application responsible for responding to the Stripe webhooks setup on port
3000. We can make this application available on the internet on port
5000 by issuing the the following command, assuming our SSH enabled and publicly available server can be reached at
$ ssh -R :3000:localhost:5000 firstname.lastname@example.org
This will log you (
user) on to the server at
server.example.com and open up port
5000 (assuming there is no firewall in the way) and forward all incoming requests on that port to our local machine on port
3000. Pay attention to the initial
: before the local port. This is the
Configuring the SSH daemon (GatewayPorts)
By default, the listening socket on the server will be bound to the loopback interface only. This may be overridden by specifying a
bind_address. By specifying an empty
bind_address the remote socket will be bound to all interfaces. It is also possible to specify an IP address here, in which case the socket will only be bound to that interface.
This will however only succeed if the SSH daemon is configured to allow non loopback interfaces to be bound. This is accomplished by editing the
/etc/ssh/sshd_config file and enabling
GatewayPorts. Since this option may become a security issue I strongly suggest that you limit this option to a limited set of users on the machine.
Match User user GatewayPorts yes
GatewayPorts to the local user named
Now reload SSH
sudo reload ssh
Phew, all done! Now you can test the connection by issuing a HTTP request to the external host/port e.g. by using curl
The request will first be handled by the publicly available server at port
5000 and then forwarded “backwards” through the previously established tunnel to your local machine at port
If the request does not appear to reach all the way though, pay attention to any error messages in the console. Enabling one or two levels of debug/verbose information will surely be a good help to find anything that is not working properly. This can be done by passing
-vvv to the
Caveats and configuration hints
In the Webhook Settings it is possible to set multiple webhooks for a particular environment (Live/Test). It is also possible to filter selected types of events that will be passed on to a particular endpoint. This is useful if you simply want to tap into an existing stream of events, or if there is a subset of events you want to debug locally.
A word of caution regarding testing from multiple application environments against a single Stripe account. All of your application environment (dev, stage, test, …) endpoints will receive all events as there is no additional levels of separation, other than Live and Test. It is usually not a big deal but worth pointing out as you will sooner or later start noticing webhook events that do not match your current environment, especially if you are simultaneously testing in multiple environments.
SSH is just amazing. Simple as that. If you have not done so already I can really suggest you check out the manual page with
man ssh, which contains some really useful commands.
To get an idea of what else SSH is capable of, I can recommend a talk called The Black Magic Of SSH / SSH Can Do That? by Bo Jeanes which highlights some of the cool things you can do with SSH, other than an actual shell.