Creating reusable developer environments with Stripe Sandboxes

/Article

When new software engineers join a team, it can take weeks to set up development machines with the right configuration of tools, permissions, and project dependencies. However, technologies such as containerization and cloud-based development environments can reduce the time it takes for new engineers to start being productive by using pre-configured development environments that spin up relatively quickly. These environments also come with the added benefit of helping enforce consistency across the team regarding operating system, runtime, and library versions.

If your project includes a payment integration with Stripe, pairing these development environments with Stripe Sandboxes provides engineers with a safe, isolated workspace where they can observe and experiment on the project without disrupting live data.

Within a Stripe sandbox account, engineers have full access to the Stripe API and can test payment functionality without needing to execute real transactions. Sandboxes can be populated with account data for testing using one of the Stripe SDKs. This allows new team members to familiarize themselves quickly with the solution’s payment workflows and understand the integration points without waiting for production access.

Preparing a Sandbox

For a given live Stripe account, there can be up to 5 sandboxes. To create a sandbox for onboarding, open the account selection menu in the top left corner of the Stripe Dashboard and select Sandboxes.

In the Create a new sandbox dialog, the only requirement is to provide a unique name for the sandbox. Optionally, settings from the live account can be copied into the sandbox to help minimize setup time even more.

Account settings are not synchronized between sandboxes and their associated live accounts. This means that further changes can be made to sandbox settings to try out new behaviors without affecting other environments.

The information copied from the production account does not include any customer, product, or transaction data. It can be beneficial if your new team members had some fake data to play around with in the sandbox. The two most common ways of doing this are by using either the fixtures feature in the Stripe CLI or one of the supported language SDKs. The following code samples demonstrate how to use C# and Stripe.net SDK to populate the sandbox account with fake product data.

Before making requests using any Stripe SDK, you first have to retrieve the secret key for the account that will be used to authenticate API requests for the given environment. Using the Developers menu in the top right navigation in the Dashboard, select API Keys and Reveal test key to get access to the secret key.

In your .NET project, install Stripe.net as well as the Bogus library that is used to create the fake data. The following code uses the Faker class from Bogus to create a list of random products.

// Generate Fake product data using Bogus; public record Product(string UniqueCode, string Name, string Description, string ImageUrl, decimal Price); public class ProductRecordFaker : Faker<Product> { public ProductRecordFaker() { this.CustomInstantiator(_ => FormatterServices.GetUninitializedObject(typeof(Product)) as Product); RuleFor(p => p.UniqueCode, f => f.Random.AlphaNumeric(7).ToUpper()); RuleFor(p => p.Name, f => f.Commerce.ProductName()); RuleFor(p => p.Description, f => $"This is such an awesome product made out of {f.Commerce.ProductMaterial()}"); RuleFor(p => p.ImageUrl, f => f.Image.PicsumUrl()); RuleFor(p => p.Price, f => Decimal.Parse(f.Commerce.Price(min:15, max:200))); } } var productFaker = new ProductRecordFaker(); var products = productFaker.Generate(10);

Next, loop through those fake products and pass them to the ProductService in Stripe.net to create Stripe products in the sandbox.

// Set your secret key StripeConfiguration.ApiKey = “sk_test_xxx”; // Create products using the generated fake data var service = new ProductService(); foreach(var product in products) { var options = new ProductCreateOptions { Name = product.Name, Description = product.Description, Images = new List<string>{ product.ImageUrl}, Shippable = true, Metadata = new Dictionary <string, string>{ ["code"] = product.UniqueCode } }; await service.CreateAsync(options); }

After running this code, the Product catalog in the Dashboard has new product data available. Depending on your use case, the SDKs can be used to further populate additional data in the account such as customer information, product pricing, and transaction records.

Configuring the development environment

Now that a sandbox has been created for the Stripe account, the next phase involves setting up a reusable developer environment that can be used by the existing team members as well as engineers being onboarded. Companies like Microsoft, GitPod, and GitHub all provide scalable offerings for cloud-based development environments (CDEs) that can be hosted for you or you can host yourself. This section shows how to configure an environment using development containers.

With development containers, you can create full featured development environments that contain all the tools, libraries and services needed to work on a software project. Using container runtimes, like Docker, allows development containers to create isolated environments that can run locally or remotely. This provides engineers with the flexibility to have a consistent workspace even if they change development machines. This approach safeguards the local filesystem since all dependencies are installed within the container, easing setup concerns and ensuring a seamless development experience for everyone on the team.

Source code editors like Visual Studio Code provide extensions that enable the use of development containers within a workspace. The following screenshot shows the layout of a sample .NET API project. It relies on a .env file to retrieve the configuration information such as the Stripe secret key and connection credentials to Redis.

To add development container support to this project, first make sure you have both Docker and the Dev Containers extension for Visual Studio Code installed. In the project’s root folder, add a .devcontainer/devcontainer.json file which defines the settings for the container workspace. A list of supported properties can be found in the development container metadata reference page.

Below sample shows the configurations of your development container including how you can customize your environment with “customizations” property. This defines the name of the workspace, the folder path VS Code opens inside of the development container when the environment is running, and VS Code specific extensions that should be installed within the workspace.

{ "name": "Products API (Dev)", // The path VS Code should open by default when connected. "workspaceFolder": "/workspace", "customizations": { "vscode": { "extensions": [ "ms-dotnettools.vscode-dotnet-pack", "ms-dotnettools.csdevkit", "humao.rest-client", "Stripe.vscode-stripe" ] } } }

For the next step, you need to add configuration for the container image that is used to run the project code. You can think of a container image like a blueprint for a miniature operating system with its own file system and processes running in an isolated space. Before running a dev container, you first have to create a blueprint.

In Docker, multiple images can be customized and run with a Docker compose file. With this project depending on Redis, an instance of a Redis server should be included in the workspace environment as well. Within the .devcontainer folder, create a compose.yml and include the following configuration.

services: redis: image: "redis/redis-stack:7.4.0-v0" ports: - "6379:6379" - "8001:8001" environment: - REDIS_ARGS="--requirepass ${REDIS_PSWD}"

The snippet above defines a Redis service using the redis/redis-stack image, exposes two ports for communication, and sets the server password with an environment variable.

Since the project is built on .NET, the image must have the correct versions of the .NET runtime and SDK installed. While you are free to create your own image, the development containers images repository on GitHub hosts a collection of reusable container images for you to get started with. You can use one of the .NET develpment container images that already has the SDK installed as the baseline to build on. The configuration below shows how to define a docker compose service for this API project.

productsapi: image: mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm volumes: - ..:/workspace:cached command: sleep infinity network_mode: service:redis

The service configuration uses a container image based on Debian (bookworm) and has the .NET 8 SDK included. It mounts the root project directory into the /workspace folder of the container, and configures the network. Redis is now available via localhost inside the development container. A completed version of the compose.yml resembles the following.

services: productsapi: image: mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm volumes: - .:/workspace:cached command: sleep infinity network_mode: service:redis redis: image: "redis/redis-stack:7.4.0-v0" restart: unless-stopped ports: - "6379:6379" - "8001:8001" environment: - REDIS_ARGS="--requirepass ${REDIS_PSWD}"

In the .devcontainer.json file, update the development container settings to use the compose file.

{ "name": "Products API (Dev)", // The compose files to use for your service "dockerComposeFile": [ "compose.yml" ], // The name of the service for the container that VS Code should use. "service": "productsapi", // Tthe path VS Code should open by default when connected. "workspaceFolder": "/workspace", // Use 'forwardPorts' to make a list of ports inside the container available locally. "forwardPorts": [ 5064 ], "customizations": { "vscode": { "extensions": [ "ms-dotnettools.vscode-dotnet-pack", "ms-dotnettools.csdevkit", "humao.rest-client", "Stripe.vscode-stripe" ] } } }

With Docker running, use the command palette in Visual Studio Code to run the Dev Containers: Reopen in Container command. In a few minutes, the development container runs with the API project mounted into the workspace.

Adding the Stripe CLI to the workspace

The VS Code customizations section above installs the Stripe extension into the workspace. For the extension to work, it requires the Stripe CLI to be installed and available on the command path. You can manually install Stripe CLI yourself with the apt command, or use bash shell script to install it automatically

Development containers allow scripts to be run at different stages of the lifecycle. This means you can write bash scripts that run after the container is created to install the Stripe CLI. In the .devcontainer.json file, add the following property.

"postCreateCommand": "bash .devcontainer/postCreate.sh"

In the .devcontainer folder, create a file named postCreate.sh with the following contents.

#!/bin/bash # Add Stripe CLI to sources list echo "Installing Stripe CLI..." curl -s https://packages.stripe.dev/api/security/keypair/stripe-cli-gpg/public | gpg --dearmor | sudo tee /usr/share/keyrings/stripe.gpg echo "deb [signed-by=/usr/share/keyrings/stripe.gpg] https://packages.stripe.dev/stripe-cli-debian-local stable main" | sudo tee -a /etc/apt/sources.list.d/stripe.list # Install dependencies sudo apt update sudo apt install stripe

Using the command palette in Visual Studio Code to run the Dev Containers: Rebuild Container command. This builds a new container image, runs the container, and executes the script.

With the completed development container configuration, check in these new configuration files into source control. Now all your engineers can work on the project in a completely isolated environment.

Conclusion

The less time engineers spend getting their environments configured, the more time for them to make valuable contributions to the team. Spending a little time upfront to build out a consistent development environment for the team can save countless hours battling configuration and versioning issues. Stripe Sandboxes and development containers make an excellent pairing to provide consistent, isolated environments that can benefit the entire team.

To learn more about developing applications with Stripe, visit our YouTube Channel.

/About the author

Cecil Phillip

Cecil Phillip is a part of the Developer Relations team at Stripe. He is originally from St. John’s, Antigua and has over a decade of experience in building software for various industries. He’s a huge fan of .NET and loves learning about patterns for building distributed systems. Feel free to reach out to him on social media, and check out some of his videos on the Stripe Developer channel.

/Related Articles
[ Fig. 1 ]
10x
Avoiding test mode tangles with Stripe Sandboxes
Discover how to create independent testing environments with Stripe Sandboxes, streamline your development through GitHub automation, and...
Sandboxes
[ Fig. 2 ]
10x
Doing more with less: Reducing requests to the Stripe API
The performance of an application can directly affect the customer experience. Using the expand feature along with caching techniques, developers...
Workbench