An open API service indexing awesome lists of open source software.

https://github.com/tempoxyz/mpp-go

Go SDK for the Machine Payments Protocol
https://github.com/tempoxyz/mpp-go

Last synced: 29 days ago
JSON representation

Go SDK for the Machine Payments Protocol

Awesome Lists containing this project

README

          








Machine Payments Protocol





# mpp-go

Go SDK for the [**Machine Payments Protocol**](https://mpp.dev)

[![Website](https://img.shields.io/badge/website-mpp.dev-black)](https://mpp.dev)
[![Docs](https://img.shields.io/badge/docs-mpp.dev-blue)](https://mpp.dev/sdk/go)
[![Go Reference](https://pkg.go.dev/badge/github.com/tempoxyz/mpp-go.svg)](https://pkg.go.dev/github.com/tempoxyz/mpp-go)
[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue)](LICENSE)

[MPP](https://mpp.dev) lets any client — agents, apps, or humans — pay for any service in the same HTTP request. It standardizes [HTTP 402](https://mpp.dev/protocol/http-402) with an open [IETF specification](https://paymentauth.org), so servers can charge and clients can pay without API keys, billing accounts, or checkout flows.
## Documentation

You can get started today by reading the [Go SDK docs](https://mpp.dev/sdk/go), the module-level [Go doc reference](https://pkg.go.dev/github.com/tempoxyz/mpp-go), exploring the [protocol overview](https://mpp.dev/protocol/), or jumping straight to the [quickstart](https://mpp.dev/quickstart/).

Package docs:

- [`pkg/client`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/client)
- [`pkg/server`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/server)
- [`pkg/tempo`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/tempo)
- [`pkg/tempo/client`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/tempo/client)
- [`pkg/tempo/server`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/tempo/server)

## Install

```bash
go get github.com/tempoxyz/mpp-go
```

## Quick Start

### Server

```go
package main

import (
"encoding/json"
"net/http"

"github.com/tempoxyz/mpp-go/pkg/server"
charge "github.com/tempoxyz/mpp-go/pkg/tempo/server"
)

func main() {
method, _ := charge.MethodFromConfig(charge.Config{
RPCURL: "https://rpc.moderato.tempo.xyz",
Recipient: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
})

payment := server.New(method, "api.example.com", "replace-me")

handler := server.ChargeMiddleware(payment, server.ChargeParams{
Amount: "0.50",
Description: "Paid content",
})(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_ = json.NewEncoder(w).Encode(map[string]any{
"data": "paid content",
"payer": server.CredentialFromContext(r.Context()).Source,
})
}))

_ = http.ListenAndServe(":8080", handler)
}
```

### Client

```go
package main

import (
"context"
"encoding/json"
"fmt"
"os"

"github.com/tempoxyz/mpp-go/pkg/client"
"github.com/tempoxyz/mpp-go/pkg/mpp"
charge "github.com/tempoxyz/mpp-go/pkg/tempo/client"
)

func main() {
method, _ := charge.New(charge.Config{
PrivateKey: os.Getenv("MPP_PRIVATE_KEY"),
RPCURL: "https://rpc.moderato.tempo.xyz",
})

c := client.New([]client.Method{method})
response, err := c.Get(context.Background(), "https://api.example.com/paid")
if err != nil {
panic(err)
}
defer response.Body.Close()

receipt, _ := mpp.ParseReceipt(response.Header.Get("Payment-Receipt"))

var body struct {
Data string `json:"data"`
Payer string `json:"payer"`
}
_ = json.NewDecoder(response.Body).Decode(&body)

fmt.Printf("paid request for %q from %s with receipt %s\n", body.Data, body.Payer, receipt.Reference)
}
```

## Examples

| Example | Description |
|---------|-------------|
| [basic](./examples/basic/) | Separate-process demo with a long-running server and standalone client, mirroring the `mpp-rs` sample layout |
| [chi/server](./examples/chi/server/) | Chi router example using the existing `net/http` middleware helpers |
| [gin/server](./examples/gin/server/) | Gin example using the dedicated adapter package and context helpers |
| [echo/server](./examples/echo/server/) | Echo example using the dedicated adapter package and context helpers |
| [fiber/server](./examples/fiber/server/) | Fiber example using the dedicated adapter package and context helpers |
| [charge-basic](./examples/charge-basic/) | Generic Tempo charge flow using the high-level MPP client and server helpers, available in both one-command and separate-process layouts |
| [charge-hash](./examples/charge-hash/) | Push-mode charge flow with a hash credential, available in both one-command and separate-process layouts |
| [charge-fee-payer](./examples/charge-fee-payer/) | Sponsored Tempo charge flow where the server co-signs as a fee payer, available in both one-command and separate-process layouts |

## Web Frameworks

The most common Go HTTP stacks today are `net/http`, Gin, Echo, Chi, and Fiber.
MPP already integrates directly with `net/http`, which also covers Chi because
Chi handlers and middleware use the standard `http.Handler` interfaces.

For the most common non-stdlib frameworks, mpp-go ships first-class adapters:

- [`pkg/server/gin`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/server/gin) for Gin
- [`pkg/server/echo`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/server/echo) for Echo
- [`pkg/server/fiber`](https://pkg.go.dev/github.com/tempoxyz/mpp-go/pkg/server/fiber) for Fiber

Chi needs no special adapter:

```go
router.With(server.ChargeMiddleware(payment, server.ChargeParams{
Amount: "0.50",
Description: "Paid content",
})).Get("/paid", func(w http.ResponseWriter, r *http.Request) {
credential := server.CredentialFromContext(r.Context())
receipt := server.ReceiptFromContext(r.Context())
_ = json.NewEncoder(w).Encode(map[string]any{
"payer": credential.Source,
"receipt": receipt.Reference,
})
})
```

Gin route middleware:

```go
router.GET("/paid", ginadapter.ChargeMiddleware(payment, server.ChargeParams{
Amount: "0.50",
Description: "Paid content",
}), func(c *gin.Context) {
credential := ginadapter.Credential(c)
receipt := ginadapter.Receipt(c)
c.JSON(http.StatusOK, gin.H{
"payer": credential.Source,
"receipt": receipt.Reference,
})
})
```

Echo route middleware:

```go
e.GET("/paid", func(c echo.Context) error {
credential := echoadapter.Credential(c)
receipt := echoadapter.Receipt(c)
return c.JSON(http.StatusOK, map[string]any{
"payer": credential.Source,
"receipt": receipt.Reference,
})
}, echoadapter.ChargeMiddleware(payment, server.ChargeParams{
Amount: "0.50",
Description: "Paid content",
}))
```

Fiber route middleware:

```go
app.Get("/paid", fiberadapter.ChargeMiddleware(payment, server.ChargeParams{
Amount: "0.50",
Description: "Paid content",
}), func(c *fiber.Ctx) error {
credential := fiberadapter.Credential(c)
receipt := fiberadapter.Receipt(c)
return c.Status(http.StatusOK).JSON(fiber.Map{
"payer": credential.Source,
"receipt": receipt.Reference,
})
})
```

## Protocol

Built on the ["Payment" HTTP Authentication Scheme](https://paymentauth.org), an open specification proposed to the IETF. See [mpp.dev/protocol](https://mpp.dev/protocol/) for the full protocol overview, or the [IETF specification](https://paymentauth.org) for the wire format.

## Contributing

```
git clone https://github.com/tempoxyz/mpp-go
cd mpp-go
go test ./...
```

## Security

See [`SECURITY.md`](./SECURITY.md) for reporting vulnerabilities.

## License

Licensed under either of [Apache License, Version 2.0](./LICENSE-APACHE) or [MIT License](./LICENSE-MIT) at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this project by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.