Skip to main content

Go SDK: github.com/oid4pay/oid4ac-go

The Go SDK targets Go 1.25+. It is a verify-only merchant library: it verifies signed offers, SD-JWT VC mandates, and catalogs. It does not settle payments. Settlement is performed by the Authorization Server, reached over HTTP, never through this SDK. The SDK depends on github.com/lestrrat-go/jwx/v2 for JOSE handling plus the OpenTelemetry SDK packages.

Install

go get github.com/oid4pay/oid4ac-go

API reference

VerifyOffer(offerBody interface{}, headers OfferSignatureHeaders, merchantJWKS *JWKSet, options VerifyOfferOptions) (*VerifiedOffer, error)

Verifies an RFC 9421 signed offer. On failure the returned error is a *VerifyError carrying a Code and Message; transport failures during a JWKS fetch return a *NetworkError. Branch on the failure mode with errors.As against the concrete error type and inspect its Code.

VerifyMandate(presentation string, merchantAudience string, options VerifyMandateOptions) (*VerifiedMandate, error)

Verifies an SD-JWT VC mandate presentation. presentation is the single compact SD-JWT VC + KB-JWT string the agent posted to the merchant; merchantAudience is the merchant's resource URL. VerifyMandateContext(ctx, presentation, merchantAudience, options) is the context-aware variant.

Example: net/http storefront handler

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

    oid4ac "github.com/oid4pay/oid4ac-go"
)

func offerHandler(w http.ResponseWriter, r *http.Request) {
    var req offerPayload
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, "bad request", http.StatusBadRequest)
        return
    }

    verified, err := oid4ac.VerifyOffer(req.OfferBody, req.SignatureHeaders, merchantJWKS,
        oid4ac.VerifyOfferOptions{
            ExpectedTargetURI: "https://shop.example.com/oid4ac/offer/" + req.SKU,
        },
    )
    if err != nil {
        var verr *oid4ac.VerifyError
        if errors.As(err, &verr) && verr.Code == "offer_signature_expired" {
            http.Error(w, "offer expired", http.StatusBadRequest)
            return
        }
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // Offer verified. The body digest is bound for the downstream
    // mandate / settlement step, which the Authorization Server
    // performs over HTTP.
    json.NewEncoder(w).Encode(map[string]string{"body_digest": verified.BodyDigest})
}

Algorithm whitelist

Identical to Node and Python: ed25519 and ecdsa-p256-sha256 for signed offers; EdDSA for mandate verification.