Learn about CELUS's AI-driven design platform for automating schematic captures and more on July 29th .

Blues Developers
What’s New
Resources
Blog
Technical articles for developers
Newsletter
The monthly Blues developer newsletter
Terminal
Connect to a Notecard in your browser
Developer Certification
Get certified on wireless connectivity with Blues
Webinars
Listing of Blues technical webinars
Blues.comNotehub.io
Shop
Docs
Button IconHelp
Notehub StatusVisit our Forum
Button IconSign In
Sign In
Sign In
What’s New
Resources
Blog
Technical articles for developers
Newsletter
The monthly Blues developer newsletter
Terminal
Connect to a Notecard in your browser
Developer Certification
Get certified on wireless connectivity with Blues
Webinars
Listing of Blues technical webinars
Blues.comNotehub.io
Shop
Docs
homechevron_rightBlogchevron_rightTaking Payments with Stripe and Notecard

Taking Payments with Stripe and Notecard

Taking Payments with Stripe and Notecard banner

July 7, 2025

Learn how to use Stripe Payment Links and Notecard to easily take payments with your IoT system.

  • Notecard
  • Stripe
Alex Bucknall
Alex BucknallStaff Developer Experience Engineer
email

Imagine you have a fleet of Notecard-connected devices that you want to take payments for. This might be vending machines, charging stations, smart lockers or smart bikes. Traditionally, integrating payments into IoT systems requires complex infrastructure, PCI compliance considerations, and significant firmware and server-side development.

Using the workflow described in this blog post you could, for example, enable a washing machine to be started upon receiving a payment. Check out the other examples in the Practical Use Cases.

This blog post demonstrates a elegant yet simple solution: using Stripe's Payment Links combined with Notecard & Notehub API to create a seamless payment experience that requires minimal code and infrastructure. This approach is incredibly straightforward, Stripe handles all the payment processing and compliance, while Notehub orchestrates the host communication using Notecard.

Find the source code for this blog post here .

How It Works

The system consists of three main components:

  1. Golang Web Server: Acts as a bridge between Stripe and Notehub, handling both payment webhooks and using the Notehub API to send notes to Notecards.
  2. Stripe Payment Links: Handles the actual payment processing and compliance.
  3. Notecard Devices: Receive payment confirmations and update their state.

This is what the complete flow looks like:

Stripe Payment Notecard Flow

The Architecture

Server Initialization

When the server starts, it performs several setup operations:

  1. Authenticates with Notehub using OAuth2 credentials to get an auth token
  2. Discovers all provisioned devices in the Notehub project
  3. Creates unique Stripe Payment Links for each device
  4. Maintains a mapping between device UIDs and their payment links

This approach means each device gets its own dedicated payment URL, making it easy to track which payments belong to which devices.

When a Payment Link is created, it is stored in a map of device UIDs to Payment Link URLs. This map is used to redirect customers to the correct payment page when they visit the /pay?device=xyz endpoint.

func (s *Server) createPaymentLink(device NotehubDevice) (string, error) {
	params := &stripe.PaymentLinkParams{
		LineItems: []*stripe.PaymentLinkLineItemParams{
			{
				Price:    stripe.String(s.stripePriceID),
				Quantity: stripe.Int64(1),
			},
		},
		Metadata: map[string]string{
			"device_uid": device.UID,
		},
	}

	link, err := paymentlink.New(params)
	if err != nil {
		return "", err
	}

	return link.URL, nil
}

Payment Processing

The payment flow is remarkably simple. When a customer visits the /pay?device=xyz endpoint, where xyz is the device UID, the server redirects them to the Stripe Payment Link for the device. No sensitive payment data ever touches your server and there's no need to worry about storing payment data.

func (s *Server) handlePayment(w http.ResponseWriter, r *http.Request) {
    deviceUID := r.URL.Query().Get("device")
    if deviceUID == "" {
        http.Error(w, "Missing device parameter", http.StatusBadRequest)
        return
    }

    s.mu.RLock()
    paymentLinkURL, exists := s.deviceLinks[deviceUID]
    s.mu.RUnlock()

    if !exists {
        http.Error(w, "Device not found", http.StatusNotFound)
        return
    }

    log.Printf("Redirecting to payment link for device %s", deviceUID)
    http.Redirect(w, r, paymentLinkURL, http.StatusTemporaryRedirect)
}

Once the payment is complete, Stripe sends a webhook to the web server, which in turn uses the Notehub API to send a note to the device.

Sending the Payment Confirmation

The arguably the most interesting part of this architecture is the sending of the payment confirmation notefile to the device. Once the payment is successful, Stripe sends a webhook to your server, which then communicates with the specific device.

This is a simplified example. Check out the GitHub repository for the full code.

func (s *Server) handleStripeWebhook(w http.ResponseWriter, r *http.Request) {
    // Verify webhook signature for security
    // Parse the webhook event
    // Extract device UID from payment metadata

    if event.Type == "checkout.session.completed" {
        deviceUID := event.Data.Object.Metadata["device_uid"]

        // Send note to the specific device
        if err := s.sendDeviceNote(deviceUID, "payment.qi", map[string]interface{}{
            "payment_status": "completed",
            "timestamp":      time.Now().Unix(),
            "session_id":     event.Data.Object.ID,
        }); err != nil {
            log.Printf("Failed to send note to device %s: %v", deviceUID, err)
        }
    }
}

Notecard receives a JSON payload in its payment.qi notefile, which it can use to update its host's state:

{
  "payment_status": "completed",
  "timestamp": 1640995200,
  "session_id": "cs_test_..."
}

Configuring Stripe

To get set up in Stripe, you'll need to create a product and price. You'll also need to set up a webhook endpoint to listen for checkout.session.completed events.

1. Create a Product and Price

First, you'll need to create a product and price in your Stripe dashboard (or as shown below using the Stripe CLI ):

# Using Stripe CLI to generate a product, e.g. prod_xxx
stripe products create --name "Notecard Payment" --description "Payment for Notecard usage"

# Using Stripe CLI to generate a price, e.g. price_xxx
stripe prices create --unit-amount 5 --currency usd --product prod_xxx

We'll need the price ID for the web server to know which price to use for the devices.

2. Configure Webhook Endpoint

Set up a webhook endpoint in Stripe to listen for checkout.session.completed events:

  1. Go to your Stripe Dashboard → Developers → Webhooks
  2. Add endpoint: https://yourdomain.com/webhook/stripe
  3. Select event: checkout.session.completed
  4. Copy the webhook signing secret to use in your .env file
note

A useful development tip is that you can use the Stripe CLI to test your webhook endpoint.

stripe listen --forward-to localhost:3000/webhook/stripe

While you're testing, all events will be routed to the local web server.

3. Environment Variables

Create a .env file with your Stripe credentials:

STRIPE_SECRET_KEY=sk_test_...
STRIPE_PRICE_ID=price_...
STRIPE_WEBHOOK_SECRET=whsec_...

Configuring Notehub

1. Create a Notehub Project

Set up a new project in Notehub and provision your Notecard devices. Each device will automatically get a unique Payment Link, when the server starts.

2. Configure OAuth2 Credentials

Generate OAuth2 credentials for your Notehub project and copy the Project UID into your .env file:

NOTEHUB_CLIENT_ID=your_client_id
NOTEHUB_CLIENT_SECRET=your_client_secret
NOTEHUB_PROJECT_UID=app:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Configuring Notecard & Host

You'll want to make sure that you configure your Notecard correctly to receive the payment notefile. To be instantanously notified of the payment, you'll want to configure Notecard to be in continuous mode and set sync to true.

J *req = notecard.newRequest("hub.set");
JAddStringToObject(req, "product", "com.my-company.my-name:my-project");
JAddStringToObject(req, "mode", "continuous");
JAddBoolToObject(req, "sync", true);
notecard.sendRequestWithRetry(req, 5);

Being in continuous mode does mean that Notecard will be drawing more power, so you'll want to make sure that you're using a mains-powered device. You could use periodic mode, but you'll need to consider how this will work given that the payment will only be received when Notecard syncs with Notehub.

Your Notecard's Host (e.g. a Swan or Cygnet) can then listen and handle the payment confirmation.

If there is a new payment.qi notefile, the host can use it to update its state. For example if this were powering an automated washing machine system, this might enable power to the washing machine or start the wash cycle.

// Arduino example
J *req = notecard.newRequest("note.get");
JAddStringToObject(req, "file", "payment.qi");
JAddBoolToObject(req, "delete", true);
J *rsp = notecard.requestAndResponse(req);

if (JGetString(rsp, "body.payment_status") != NULL) {
    const char *status = JGetString(rsp, "body.payment_status");
    if (strcmp(status, "completed") == 0) {
        // Payment confirmed! Enable service, start the wash cycle, dispense product, etc.
        enableService();
    }
}

Using the Notecard QR Code

Handily, every Notecard comes with a pre-provisioned QR code sticker which can be used to direct a URL to a custom dashboard. A customer could simply scan the QR code to be redirected to the payment page.

Notehub provides a domain, qrgo.org, that redirects requests for qrgo.org/id/[deviceUID] to a dashboard URL that you can configure. This workflow allows you to use the loose stickers provided with each Notecard, or to print your own QR codes, that point to qrgo.org/id/[deviceUID] on physical devices, and configure the final resolved URL in Notehub.

If you want to set these up for the stripe payment example, you can set the dashboard URL to https://yourdomain.com/pay?device=[deviceUID].

Running the Demo

# Clone and setup
git clone https://github.com/Bucknalla/note-stripe-payment
cd note-stripe-payment

# Install dependencies (At least Go 1.22 is required)
go mod tidy

# Configure environment variables
cp .env.example .env
# Edit .env with your credentials

# Run the server
go run main.go

The server exposes several endpoints:

  • /pay?device=dev:123456 - Redirect to payment for specific device
  • /webhook/stripe - Stripe webhook handler
  • /refresh-devices - Manually refresh device list
  • /health - System status and device count

Practical Use Cases

This architecture will work for several IoT scenarios:

Vending Machines

  • Customer scans QR code with device UID
  • Gets redirected to payment page
  • After payment, machine dispenses product

EV Charging Stations

  • Driver enters device ID or scans QR code
  • Pays for charging session
  • Charging station receives confirmation and activates

Smart Lockers

  • User pays for locker rental
  • Locker receives payment confirmation
  • Locker unlocks and starts rental period

Parking Meters

  • Driver pays for parking time
  • Meter receives payment confirmation
  • Meter activates for specified duration

Benefits of This Approach

For Developers of IoT systems, this approach offers:

  • Minimal Code: The entire server is less than 400 lines of Go
  • No PCI Compliance: Stripe handles all payment security
  • Scalable: Automatically works with any number of devices
  • Reliable: Built on proven Stripe and Notecard infrastructure

For Businesses, this approach offers:

  • Quick Time-to-Market: Get payments working in hours, not weeks
  • Low Operational Overhead: No payment infrastructure to maintain
  • Global Reach: Stripe supports payments in 135+ currencies
  • Real-time Notifications: Devices know immediately when payments complete

Considerations for Production

While this is a great starting point for a proof of concept, there are a few things to consider for production.

  • Robust Data Storage: Consider how you'll store the mapping between device UIDs and Payment Links.
  • Improved Error Handling: Consider more appropriate error handling for Stripe and Notehub.
  • Dyanmic Price ID: Consider how you'll handle dynamic price IDs for the devices, this could use Notehub Environment Variables.

The system includes several security best practices but it's worth considering:

  • Webhook Signature Verification: Ensures webhooks actually come from Stripe
  • Environment Variables: Keeps sensitive credentials secure
  • OAuth2 Authentication: Secure API access to Notehub
  • No Payment Data Storage: All payment processing happens on Stripe's servers
  • Encrypted Communication: Consider using encryption to secure the communication between Notehub and Notecard

Conclusion

This blog post demonstrates how modern payment APIs and IoT connectivity can work together to create powerful, yet simple solutions. By leveraging Stripe's payment expertise and Notecard's IoT connectivity, you can add payments to your IoT devices without the complexity typically associated with such integrations.

The combination of Stripe Payment Links and Notecard devices creates a robust foundation for IoT commerce applications, whether you're building the next generation of vending machines, charging stations, or an entirely new category of connected devices.

In This Article

  • How It Works
  • The Architecture
    • Server Initialization
    • Payment Processing
    • Sending the Payment Confirmation
  • Configuring Stripe
    • 1. Create a Product and Price
    • 2. Configure Webhook Endpoint
    • 3. Environment Variables
  • Configuring Notehub
    • 1. Create a Notehub Project
    • 2. Configure OAuth2 Credentials
  • Configuring Notecard & Host
    • Using the Notecard QR Code
  • Running the Demo
  • Practical Use Cases
    • Vending Machines
    • EV Charging Stations
    • Smart Lockers
    • Parking Meters
  • Benefits of This Approach
  • Considerations for Production
  • Conclusion

Blues Developer News

The latest IoT news for developers, delivered right to your inbox.

Comments

Join the conversation for this article on our Community Forum

Blues Developer Newsletter

The latest IoT news for developers, delivered right to your inbox.

© 2025 Blues Inc.
© 2025 Blues Inc.
TermsPrivacy
Notecard Disconnected
Having trouble connecting?

Try changing your USB cable as some cables do not support transferring data. If that does not solve your problem, contact us at support@blues.com and we will get you set up with another tool to communicate with the Notecard.

Advanced Usage

The help command gives more info.

Connect a Notecard
Use USB to connect and start issuing requests from the browser.
Try Notecard Simulator
Experiment with Notecard's latest firmware on a Simulator assigned to your free Notehub account.

Don't have an account? Sign up