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-goAPI 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.