Skip to content

Commit 50f02ee

Browse files
committed
feat: add go sdk blogpost
1 parent d970e02 commit 50f02ee

File tree

2 files changed

+258
-1
lines changed

2 files changed

+258
-1
lines changed
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
---
2+
title: "Go Further with Open Payments"
3+
description: "Announcing the Open Payments Go SDK"
4+
date: 2025-12-19
5+
slug: go-further-with-open-payments
6+
authors:
7+
- Blair Currey
8+
author_urls:
9+
- https://www.linkedin.com/in/blair-currey/
10+
tags:
11+
- Open Payments
12+
- Releases
13+
- Updates
14+
---
15+
16+
## Why Open Payments in Go?
17+
18+
The [**Open Payments**](https://openpayments.dev/) standard is reshaping how applications initiate, manage, and complete digital transactions β€” enabling truly interoperable financial systems across different wallets, services, and financial institutions.
19+
20+
The Interledger Foundation has been steadily expanding SDK support across languages β€” [Node](https://github.com/interledger/open-payments-node) led the way, followed by [PHP](https://github.com/interledger/open-payments-php) and [Rust](https://github.com/interledger/open-payments-rust). But one language was notably missing: **Go**.
21+
22+
According to the [2025 Stack Overflow Developer Survey](https://survey.stackoverflow.co/2025/technology#worked-with-vs-want-to-work-with-language-worked-want), Go ranks among the top backend languages, sitting alongside TypeScript and Python in developer adoption. Perhaps more tellingly, the survey notes that "Python developers aspire to use Rust and Go as the path to high-performance systems programming" β€” reflecting Go's growing role in cloud infrastructure, microservices, and performance-critical backends.
23+
24+
Today, we're excited to close that gap with [**Open Payments Go**](https://github.com/interledger/open-payments-go) β€” an open-source SDK that brings first-class Open Payments support to the Go ecosystem.
25+
26+
## What We Built
27+
28+
[interledger/open-payments-go](https://github.com/interledger/open-payments-go) is a production-ready Go module that provides complete client support for the Open Payments API.
29+
30+
It includes:
31+
32+
- Complete API coverage β€” wallet addresses, grants, tokens, quotes, incoming payments, and outgoing payments.
33+
- Built for Go 1.21+, leveraging Go's strong typing, interfaces, and standard library conventions.
34+
- **Types generated directly from OpenAPI specifications** using [oapi-codegen](https://github.com/oapi-codegen/oapi-codegen), ensuring the SDK stays in sync with the Open Payments spec.
35+
- Built-in HTTP signature utilities for [GNAP authentication](https://openpayments.dev/identity/http-signatures/), abstracting away the complexity of Ed25519 signing.
36+
- Comprehensive integration tests against both local Rafiki environments and testnet.
37+
38+
Here's what it looks like to request a grant and create an incoming payment:
39+
40+
```go
41+
package main
42+
43+
import (
44+
"context"
45+
"log"
46+
"time"
47+
48+
openpayments "github.com/interledger/open-payments-go"
49+
as "github.com/interledger/open-payments-go/generated/authserver"
50+
rs "github.com/interledger/open-payments-go/generated/resourceserver"
51+
)
52+
53+
func main() {
54+
privateKeyBase64 := os.Getenv("BASE64_PRIVATE_KEY")
55+
keyId := os.Getenv("KEY_ID")
56+
57+
// Initialize the authenticated client
58+
client, err := openpayments.NewAuthenticatedClient(
59+
"https://wallet.example.com/alice", // Your wallet address
60+
privateKeyBase64,
61+
keyId,
62+
)
63+
if err != nil {
64+
log.Fatal(err)
65+
}
66+
67+
// Get wallet address info
68+
wallet, err := client.WalletAddress.Get(context.Background(), openpayments.WalletAddressGetParams{
69+
URL: "https://wallet.example.com/alice",
70+
})
71+
if err != nil {
72+
log.Fatal(err)
73+
}
74+
75+
// Build the access request
76+
incomingAccess := as.AccessIncoming{
77+
Type: as.IncomingPayment,
78+
Actions: []as.AccessIncomingActions{
79+
as.AccessIncomingActionsCreate,
80+
as.AccessIncomingActionsRead,
81+
as.AccessIncomingActionsList,
82+
as.AccessIncomingActionsComplete,
83+
},
84+
}
85+
accessItem := as.AccessItem{}
86+
accessItem.FromAccessIncoming(incomingAccess)
87+
88+
// Request a grant
89+
grant, err := client.Grant.Request(context.Background(), openpayments.GrantRequestParams{
90+
URL: *wallet.AuthServer,
91+
RequestBody: as.GrantRequestWithAccessToken{
92+
AccessToken: struct {
93+
Access as.Access `json:"access"`
94+
}{
95+
Access: []as.AccessItem{accessItem},
96+
},
97+
},
98+
})
99+
if err != nil {
100+
log.Fatal(err)
101+
}
102+
103+
// Create an incoming payment
104+
expiresAt := time.Now().Add(24 * time.Hour)
105+
payment, err := client.IncomingPayment.Create(context.Background(), openpayments.IncomingPaymentCreateParams{
106+
BaseURL: *wallet.ResourceServer,
107+
AccessToken: grant.AccessToken.Value,
108+
Payload: rs.CreateIncomingPaymentJSONBody{
109+
WalletAddressSchema: *wallet.Id,
110+
IncomingAmount: &rs.Amount{
111+
Value: "1000",
112+
AssetCode: wallet.AssetCode,
113+
AssetScale: wallet.AssetScale,
114+
},
115+
ExpiresAt: &expiresAt,
116+
},
117+
})
118+
if err != nil {
119+
log.Fatal(err)
120+
}
121+
122+
log.Printf("Created incoming payment: %s", *payment.Id)
123+
}
124+
```
125+
126+
With Go's strong typing and the SDK's clean API design, developers get compile-time safety and IDE autocompletion for the entire Open Payments workflow.
127+
128+
## How It Works: Inside the Library
129+
130+
Open Payments Go is designed around Go idioms and best practices, making it feel natural for Go developers while handling the complexity of the Open Payments protocol.
131+
132+
### Project Structure
133+
134+
| Package | Purpose |
135+
| ------------------------------- | --------------------------------------------------------------- |
136+
| `openpayments` (root) | Main client types, service implementations, and public API |
137+
| `generated/authserver` | Types generated from the Auth Server OpenAPI spec |
138+
| `generated/resourceserver` | Types generated from the Resource Server OpenAPI spec |
139+
| `generated/walletaddressserver` | Types generated from the Wallet Address Server OpenAPI spec |
140+
| `httpsignatureutils` | HTTP signature creation and validation utilities |
141+
| `test/integration` | Integration tests against Rafiki local and testnet environments |
142+
143+
### Service-Oriented Architecture
144+
145+
Each Open Payments resource has a dedicated service with methods that map directly to API operations:
146+
147+
- `client.WalletAddress.Get()`, `GetKeys()`, `GetDIDDocument()`
148+
- `client.Grant.Request()`, `Continue()`, `Cancel()`
149+
- `client.IncomingPayment.Create()`, `Get()`, `List()`, `Complete()`, `GetPublic()`
150+
- `client.OutgoingPayment.Create()`, `Get()`, `List()`
151+
- `client.Quote.Create()`, `Get()`
152+
- `client.Token.Rotate()`, `Revoke()`
153+
154+
### Type-Safe Generated Types with OpenAPI Overlays
155+
156+
One challenge we faced was that the upstream OpenAPI specifications didn't always produce ideal Go types when run through code generators. For example, request bodies for grants and outgoing payments used `oneOf` unions that resulted in awkward generated type names like `PostRequestJSONBody`.
157+
158+
To solve this, we leveraged [OpenAPI Overlays](https://learn.openapis.org/overlay/) β€” a powerful technique for modifying OpenAPI specs without forking them. Our overlay files (`authserver.overlay.yaml`, `resourceserver.overlay.yaml`) add explicit type names and restructure unions for better Go ergonomics:
159+
```yaml
160+
# resourceserver.overlay.yaml
161+
actions:
162+
- target: $.components.schemas
163+
update:
164+
CreateOutgoingPaymentWithQuote:
165+
type: object
166+
required: [walletAddress, quoteId]
167+
properties:
168+
walletAddress:
169+
$ref: "#/components/schemas/walletAddress"
170+
quoteId:
171+
type: string
172+
metadata:
173+
type: object
174+
additionalProperties: true
175+
176+
CreateOutgoingPaymentWithAmount:
177+
type: object
178+
required: [walletAddress, incomingPayment, debitAmount]
179+
# ...
180+
```
181+
182+
Instead of wrestling with anonymous types, you get clear, self-documenting structs:
183+
```go
184+
// Without overlays: confusing generated names
185+
var payload PostRequestJSONBody // What is this?
186+
187+
// With overlays: intent is obvious
188+
var payload rs.CreateOutgoingPaymentWithQuote
189+
payload.WalletAddressSchema = walletAddress
190+
payload.QuoteId = quoteId
191+
```
192+
193+
This approach keeps us in sync with upstream specs while producing clean, well-named Go types.
194+
195+
### HTTP Signatures Made Simple
196+
197+
Open Payments requires [HTTP Message Signatures](https://openpayments.dev/introduction/http-signatures/) for authenticated requests. The SDK handles this complexity internally through the `httpsignatureutils` package:
198+
199+
The SDK automatically signs requests when using `AuthenticatedClient`. Internally, it:
200+
201+
1. Computes `Content-Digest` for request bodies
202+
2. Builds the signature base string per RFC 9421
203+
3. Signs with your Ed25519 private key
204+
4. Sets `Signature` and `Signature-Input` headers
205+
206+
## Why It Matters for the Go Community
207+
208+
Go powers a significant portion of cloud infrastructure, payment systems, and fintech backends. By bringing native Open Payments support to Go, we enable:
209+
210+
- **Cloud-native payment integrations**: Deploy Open Payments clients as microservices, serverless functions, or embedded in existing Go applications.
211+
212+
- **High-performance payment processing**: Go's concurrency model and low overhead make it ideal for high-throughput payment scenarios.
213+
214+
- **Type safety at compile time**: Catch integration errors before runtime with Go's strong typing and the SDK's generated types.
215+
216+
- **Battle-tested**: Comprehensive integration tests run against both local Rafiki environments and the Interledger testnet, ensuring real-world reliability.
217+
218+
## Getting Started
219+
220+
Install the SDK:
221+
222+
```bash
223+
go get github.com/interledger/open-payments-go
224+
```
225+
226+
The SDK requires Go 1.21 or later. For development, you'll also need to initialize the OpenAPI spec submodule:
227+
228+
```bash
229+
git submodule update --init
230+
```
231+
232+
To regenerate types from the specs (if you're contributing or customizing):
233+
234+
```bash
235+
go generate ./generated
236+
```
237+
238+
## What's Next
239+
240+
We're actively developing Open Payments Go and have exciting plans ahead:
241+
242+
- **Official documentation integration** β€” Open Payments docs will include Go examples alongside JavaScript, TypeScript, and PHP examples.
243+
244+
- **Community feedback** β€” We want to hear from you! Open issues, submit PRs, or join discussions on GitHub.
245+
246+
## Resources
247+
248+
- GitHub: [interledger/open-payments-go](https://github.com/interledger/open-payments-go)
249+
- [Open Payments Specification](https://openpayments.dev/)
250+
- [Interledger Foundation](https://interledger.org/)
251+
- [Rafiki β€” Open Payments Reference Implementation](https://github.com/interledger/rafiki)
252+
253+
---
254+
255+
We're excited to bring Open Payments to the Go ecosystem and can't wait to see what the community builds.
256+
257+
Give it a try, and let us know what you think! πŸš€

β€Žsrc/content/docs/get-involved.mdβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ If you are most comfortable working with **Angular**, you can contribute to [Tes
1818

1919
If you are most comfortable working with the **Web Extensions API**, you can contribute to the [Web Monetization Extension](https://github.com/interledger/web-monetization-extension)
2020

21-
If you are most comfortable in either **Python**, **Go**, **Rust**, **PHP**, **Ruby** or **.Net**, you can contribute to porting the [Open Payments SDK](https://github.com/interledger/open-payments) to the any of the aforementioned languages.
21+
If you are most comfortable in either **Python**, **Ruby** or **.Net**, you can contribute to porting the [Open Payments SDK](https://github.com/interledger/open-payments) to the any of the aforementioned languages.
2222

2323
If you have experience working on browser engines, you can contribute to the [Chromium](https://issues.chromium.org/issues/40110471) browser implementation of Web Monetization.
2424

0 commit comments

Comments
Β (0)