Automating Payments with Stripe and Golang: A Developer’s Guide

Rohit Singh
4 min readMay 1, 2024

--

Many online platforms, including Apple Media Services and AWS, improve user convenience by storing payment details like credit card or UPI information, enabling automatic payments. This setup allows them to seamlessly deduct charges for services at regular intervals or based on usage, simplifying the billing process and ensuring uninterrupted service delivery. Customers enjoy a hassle-free experience as they continue to receive services without manual payment efforts each billing cycle. This auto-payment system is essential for businesses operating on a subscription model or those charging based on actual usage, providing smooth financial operations that enhance both user convenience and company efficiency.

In this post, we will demonstrate how to integrate this feature using the Go programming language and the Stripe payment platform within the Gin framework. Start by generating your Stripe API key from the Stripe Developer Portal.

Use the below link to generate the strip-api-key
https://dashboard.stripe.com/test/apikeys

Once you get the api key lets’s begin to implement it
1. First of all create a customer using stripe key and provide name, email, address of customer

type StripeProvider struct {
SecretKey string
}
func (s *StripeProvider) CreateCustomer() (*stripe.Customer, error) {
stripe.Key = s.SecretKey
params := &stripe.CustomerParams{
Name: stripe.String("John Dey"),
Email: stripe.String("abcd123@gmail.com"),
Address: &stripe.AddressParams{
Line1: stripe.String("1234 Elm St"),
City: stripe.String("Smalltown"),
PostalCode: stripe.String("12345"),
State: stripe.String("CA"),
Country: stripe.String("US"),
},
}
result, err := customer.New(params)
return result, nil
}

using above script you can create the customer in stripe and in return you will get the customer_id from stripe some sorts of like this : cus_Aqro4nFfTo0E8v.

Obtaining the customer ID is crucial for setting up automatic payments. Once we have this ID, we can create a checkout session for the customer to select their preferred payment method. For example, if they choose to use a card, we can initiate a checkout session accordingly.

func (s *StripeProvider) CreateCheckoutSession() (*stripe.CheckoutSession, error) {
stripe.Key = s.SecretKey
params := &stripe.CheckoutSessionParams{
SuccessURL: stripe.String("https://example.com/success"),
Mode: stripe.String("setup"),
Customer: stripe.String("cus_HKtmyFxyxPZQDm"),
PaymentMethodTypes: stripe.StringSlice([]string{
"card",
}),
}
result, err := session.New(params)
return result, nil
}

The success URL is where customers are redirected after saving their card details with Stripe. The response will contain various details, but only the essential information is included at this stage.

{
"data": {
"sessionId": "cs_test_c1vTIqOhhs9db05IFiZuanbTcHgboHu2aOLbpjsbVagkY08h4muUJ07Nmo",
"successUrl": "http://localhost:8088/session/successfull",
"saveInfoUrl": "https://checkout.stripe.com/c/pay/cs_test_c1vTIqOhhs9db05IFiZuanbTcHgboHu2aOLbpjsbVagkY08h4muUJ07Nmo#fidkdWxOYHwnPyd1blpxYHZxWjA0SnR3ZE5WT2JUfEN2ZmQ1RkJ2NGdddn10QUJNclUza3FfY2xffHxsVWdBT1ZiYWxLXUEzPTx%2FYWI1PXZqdXMyMlZsZ0liQ3ZoNHVHZkkktAZ013c0t1cm5NNTVhRGl2RHBDUycpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBaZmppcGhrJyknYGtkZ2lgVWlkZmBtamlhYHd2Jz9xd3BgeCUl"
},
"message": "Customer checkout done successfully !!"
}

Now customers are suppose to click on the saveInfoUrl and they will be redirected to save their card details just like below:

A key challenge is determining in real-time when a customer has saved their card details. To address this, we can use webhooks. We need to subscribe to certain events from our Stripe dashboard and provide a secure HTTPS URL. This URL can be set up using ngrok or another hosting service, where we will implement the webhook logic.
https://dashboard.stripe.com/test/webhooks/create

I have subscribed to three events: charge.failed, charge.succeeded, and setup_intent.succeeded. When a user saves their card information, our webhook instantly detects the setup_intent.succeeded event. This allows us to extract the payment_method ID from the webhook logs, which is essential for initiating payments.

By utilizing this payment_method ID, you can charge specific amounts to the user by enabling the OffSession field in the payment intent method. This setting is crucial for facilitating recurring payments or automated transactions. Below is how your code should be configured:

func (s *StripeProvider) CreatePaymentIntent() (*stripe.PaymentIntent, error) {
stripe.Key = s.SecretKey // Assume `SecretKey` has been properly set
params := &stripe.PaymentIntentParams{
Amount: stripe.Int64(1000000), // Assuming `Balance` from the request is the amount in cents
Currency: stripe.String("usd"), // Currency such as "usd"
Confirm: stripe.Bool(true),
PaymentMethod: stripe.String("payment_method_id after saving card"),
PaymentMethodTypes: stripe.StringSlice(["card"]),
Customer: stripe.String(customer_id), // Example customer ID from the input
OffSession: stripe.Bool(true),
ConfirmationMethod: stripe.String("automatic"),
Description: stripe.String("Example payment intent for invoice"), // Description of the transaction
Shipping: &stripe.ShippingDetailsParams{
Name: stripe.String("John Doe"),
Address: &stripe.AddressParams{
Line1: stripe.String("1234 Main Street"),
PostalCode: stripe.String("94105"),
City: stripe.String("San Francisco"),
State: stripe.String("CA"),
Country: stripe.String("US"),
},
},
}

result, err := paymentintent.New(params)
return result, err
}

After calling this API and subscribing to the charge.success and charge.failed events, you can monitor the logs on your Stripe dashboard. If the payment is successful, the status will show as "succeeded," and you can confirm that the funds have been debited by viewing the transactions on the Stripe dashboard.

You can schedule this process to run repeatedly or set up a cron job to execute at specific intervals, allowing for charges to be applied based on service usage.

--

--

Rohit Singh

Backend Developer @School Hack || MERN || Go || Asynq || Blockchain || Redis || bullmq || Python || Django || Langchain || FastAPI. x- @rohit_nitc271