vtex

package
v0.4.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package vtex is a client for the public VTEX storefront APIs: catalog search, checkout orderForm, delivery simulation, VTEX ID auth, and order history.

Nothing here is store-specific. Every store-dependent value comes from the store.Store descriptor the client is constructed with.

Index

Constants

View Source
const DefaultWishlistName = "Wishlist"

DefaultWishlistName is the list vtex.wish-list writes to when the storefront's heart icon is used.

Variables

View Source
var ErrAccessKeyRequired = errors.New("store requires an emailed access code")

ErrAccessKeyRequired reports that the only login method the store offers is an emailed access code, which cannot complete in a single call. The caller must run SendAccessCode, collect the code, then ValidateAccessCode.

Functions

func GenerateClearSaleSession

func GenerateClearSaleSession(doer store.HTTPDoer, endpoint string) (string, error)

GenerateClearSaleSession registers an anti-fraud device fingerprint and returns the session ID to send as deviceFingerprint on a card payment.

Nothing here is store-specific — the app key and SDK identifiers are common to the VTEX/ClearSale integration — so it lives in the library and is reached only when a store sets the ClearSaleFingerprint quirk.

doer and endpoint are injected: the original implementation called the package-level http.Get, which bypassed the client's transport and had no timeout, so a hung ClearSale host stalled checkout indefinitely.

Types

type Client

type Client struct {

	// GatewayURL overrides the payment gateway host. Tests set it; empty
	// means the production vtexpayments host derived from the account.
	GatewayURL string
	// ClearSaleURL overrides the ClearSale fingerprint host for tests.
	ClearSaleURL string
	// contains filtered or unexported fields
}

func New

func New(s store.Store, authToken string) *Client

func (*Client) AddToCart

func (c *Client) AddToCart(orderFormID, skuID, seller string, quantity int) (*OrderForm, error)

AddToCart adds a SKU. The seller comes from the caller — normally straight off a SearchResult — because it is not a store-wide constant.

func (*Client) AddToWishlist added in v0.4.0

func (c *Client) AddToWishlist(shopperID, listName string, item WishlistItem) error

AddToWishlist saves a product to the shopper's wishlist. productID and sku differ for products with variants and the API wants both.

func (*Client) AuthStart

func (c *Client) AuthStart() (*store.Capabilities, error)

AuthStart probes what login methods this store supports.

func (*Client) AuthToken

func (c *Client) AuthToken() string

func (*Client) AuthenticatedUser

func (c *Client) AuthenticatedUser() (string, error)

AuthenticatedUser returns the logged-in email, or an error when the stored token has expired.

func (*Client) ClassicLogin

func (c *Client) ClassicLogin(email, password string) (string, error)

ClassicLogin authenticates with email and password against stock VTEX ID.

func (*Client) GatewayCallback

func (c *Client) GatewayCallback(orderGroup string) error

GatewayCallback finalizes a card payment. The gateway answers 428 while the transaction is still settling, so this retries with a linear backoff.

func (*Client) Get

func (c *Client) Get(path string) ([]byte, error)

func (*Client) GetDeliveryWindows

func (c *Client) GetDeliveryWindows(orderFormID string) ([]DeliveryWindow, error)

GetDeliveryWindows lists the windows available for the cart's address. Requires an orderForm with a shipping address, so it needs authentication; use Simulate for an unauthenticated check.

Windows are deduplicated across items and reindexed from zero, because `--window N` indexes into the returned slice.

func (*Client) GetOrder

func (c *Client) GetOrder(orderID string) (*OrderDetail, error)

func (*Client) GetOrderForm

func (c *Client) GetOrderForm(orderFormID string) (*OrderForm, error)

func (*Client) GetSavedCards

func (c *Client) GetSavedCards(orderFormID string) ([]SavedCard, error)

func (*Client) GetSession

func (c *Client) GetSession() (*Session, error)

GetSession reads the auth cookie, cart pointer, and logged-in email from the VTEX sessions API.

The auth cookie key is account-scoped (VtexIdclientAutCookie_frescatto), so the response cannot be unmarshalled through a fixed struct tag the way the pre-extraction implementations did. It is decoded into a map and looked up by the descriptor's cookie name.

func (*Client) HTTPClient

func (c *Client) HTTPClient() *http.Client

func (*Client) ListOrders

func (c *Client) ListOrders() ([]Order, error)

func (*Client) Login

func (c *Client) Login(ctx context.Context, email, password string) (string, error)

Login authenticates with whichever strategy the store supports, preferring a registered OAuth driver, then classic email+password, then access key.

The strategy is discovered rather than declared: a store descriptor does not say how to log in, the storefront does.

func (*Client) NewOrderForm

func (c *Client) NewOrderForm() (*OrderForm, error)

NewOrderForm mints a genuinely new cart.

It must use its own cookie jar: VTEX pins a client to its current cart via a checkout cookie, so calling GET /orderForm on a client that has already touched a cart hands back that same cart. Without a clean jar this silently returns the cart you were trying to escape.

func (*Client) PatchJSON

func (c *Client) PatchJSON(path string, payload any) ([]byte, error)

func (*Client) PayWithSavedCard

func (c *Client) PayWithSavedCard(tx *TransactionResult, card SavedCard, cvv string, orderValue money.Centavos) error

PayWithSavedCard submits a card payment to the VTEX payment gateway.

ClearSale fingerprinting is applied only for stores carrying the ClearSaleFingerprint quirk. Zona Sul's gateway rejects card payments without it (Cielo code 59); Frescatto shows no sign of needing it.

func (*Client) PlaceOrder

func (c *Client) PlaceOrder(orderFormID string, orderValue money.Centavos) (*TransactionResult, error)

PlaceOrder converts the cart into a transaction. This is the point of no return for non-card payments.

func (*Client) PostForm

func (c *Client) PostForm(path string, values url.Values) ([]byte, error)

PostForm submits form-encoded values. VTEX ID's validate endpoints reject JSON bodies, so auth uses this rather than PostJSON.

func (*Client) PostJSON

func (c *Client) PostJSON(path string, payload any) ([]byte, error)

func (*Client) PostJSONAbsolute

func (c *Client) PostJSONAbsolute(absoluteURL string, payload any) ([]byte, error)

PostJSONAbsolute posts to a full URL rather than a storefront path. The payment gateway lives on a different host, so it cannot use PostJSON.

func (*Client) RefreshToken

func (c *Client) RefreshToken() (string, error)

RefreshToken asks the sessions API for a fresher JWT. It returns an empty string when the session carries no token, which means the caller must re-authenticate rather than treat it as an error.

func (*Client) RemoveAllItems

func (c *Client) RemoveAllItems(orderFormID string) error

func (*Client) RemoveFromWishlist added in v0.4.0

func (c *Client) RemoveFromWishlist(shopperID, listName string, id int) (bool, error)

RemoveFromWishlist deletes an item by its wishlist ID, which is not the SKU. Callers resolve a SKU to an ID by reading the list first.

func (*Client) ResolvePaymentSystem

func (c *Client) ResolvePaymentSystem(of *OrderForm, name string) (int, error)

ResolvePaymentSystem maps a human name such as "pix" to the store's own payment system ID, discovered from the order form. IDs are not portable between stores, so this replaces the hardcoded map the CLIs used to carry.

func (*Client) Search

func (c *Client) Search(query string, limit int) ([]SearchResult, error)

Search queries the store catalog using the descriptor's configured mode.

SearchAuto tries Intelligent Search REST first and falls back to the catalog REST API. Neither needs a persisted GraphQL hash, which is what made the previous implementation brittle: VTEX rotates that hash on every search-graphql release and a stale one returns no results.

func (*Client) SendAccessCode

func (c *Client) SendAccessCode(email string) error

SendAccessCode emails a one-time login code and records the pending authentication token, which the subsequent validate call must reuse.

func (*Client) SetAddress

func (c *Client) SetAddress(orderFormID string, numItems int) error

SetAddress applies the account's saved delivery address to the cart.

func (*Client) SetAuthToken

func (c *Client) SetAuthToken(token string)

func (*Client) SetPayment

func (c *Client) SetPayment(orderFormID string, paymentSystemID int, value money.Centavos) error

func (*Client) SetPaymentWithSavedCard

func (c *Client) SetPaymentWithSavedCard(orderFormID string, card SavedCard, value money.Centavos) error

func (*Client) SetShippingWindow

func (c *Client) SetShippingWindow(orderFormID string, window DeliveryWindow, numItems int) error

SetShippingWindow selects a delivery window for every item in the cart.

func (*Client) Simulate

func (c *Client) Simulate(items []SimulationItemRequest, cep string) (*Simulation, error)

Simulate prices a basket against a postal code without authentication. This is how delivery windows and payment methods can be inspected before anyone logs in.

func (*Client) Store

func (c *Client) Store() store.Store

func (*Client) UpdateItemQuantity

func (c *Client) UpdateItemQuantity(orderFormID string, index, quantity int) (*OrderForm, error)

UpdateItemQuantity sets an absolute quantity, not a delta. Setting 0 removes the item.

func (*Client) UsableCart

func (c *Client) UsableCart(persistedID string) (*OrderForm, bool, error)

UsableCart returns a cart that can actually complete a checkout.

VTEX snapshots account data into an order form at creation time and never refreshes it — refreshOutdatedData does not help. A cart minted before the account had a profile or address is therefore permanently unusable, and because the CLI persists a cart id across invocations, a user who tried the CLI before completing their profile would be stuck forever with no way out but deleting the config by hand.

When the persisted cart cannot check out, this mints a fresh one and carries the items across, so nothing the user added is lost.

func (*Client) ValidateAccessCode

func (c *Client) ValidateAccessCode(code, emailOverride string) (string, string, error)

ValidateAccessCode exchanges an emailed code for a JWT. It returns the token and the email it authenticated, then clears the pending record.

func (*Client) Wishlists added in v0.2.0

func (c *Client) Wishlists(shopperID string) ([]Wishlist, error)

Wishlists returns the shopper's server-side wishlists — the same lists the storefront's heart icons write to.

type DeliveryWindow

type DeliveryWindow struct {
	Index    int            `json:"index"`
	Start    time.Time      `json:"start"`
	End      time.Time      `json:"end"`
	Price    money.Centavos `json:"price"`
	LisPrice money.Centavos `json:"lisPrice"`
	Tax      money.Centavos `json:"tax"`
	// RawStart and RawEnd preserve the exact strings VTEX sent. The
	// shipping-window request must echo them back byte for byte; a
	// re-formatted timestamp is rejected.
	RawStart string `json:"-"`
	RawEnd   string `json:"-"`
}

type Order

type Order struct {
	OrderID           string         `json:"orderId"`
	CreationDate      string         `json:"creationDate"`
	Status            string         `json:"status"`
	StatusDescription string         `json:"statusDescription"`
	TotalValue        money.Centavos `json:"totalValue"`
	TotalItems        int            `json:"totalItems"`
}

type OrderDetail

type OrderDetail struct {
	OrderID string      `json:"orderId"`
	Status  string      `json:"status"`
	Items   []OrderItem `json:"items"`
}

type OrderForm

type OrderForm struct {
	OrderFormID    string          `json:"orderFormId"`
	Items          []OrderFormItem `json:"items"`
	Totalizers     []Totalizer     `json:"totalizers"`
	PaymentSystems []PaymentSystem `json:"-"`
	Value          money.Centavos  `json:"value"`
	LoggedIn       bool            `json:"loggedIn"`
	// AddressCount is how many delivery addresses this cart can see. VTEX
	// snapshots account data into an order form when it is created, so a
	// cart minted before the account had an address reports zero here
	// forever — it can never complete a checkout.
	AddressCount int `json:"addressCount"`
}

func (*OrderForm) Checkoutable

func (o *OrderForm) Checkoutable() bool

Checkoutable reports whether this cart can reach a completed order. A cart with no visible address cannot, regardless of what the account has.

func (*OrderForm) ItemsTotal

func (o *OrderForm) ItemsTotal() money.Centavos

ItemsTotal returns the Items totalizer, which excludes shipping. Checkout minimums are assessed against this, not the order total.

func (*OrderForm) Total

func (o *OrderForm) Total() money.Centavos

Total sums every totalizer: items, discounts, and shipping.

type OrderFormItem

type OrderFormItem struct {
	ID           string         `json:"id"`
	ProductID    string         `json:"productId"`
	Name         string         `json:"name"`
	Quantity     int            `json:"quantity"`
	Price        money.Centavos `json:"price"`
	SellingPrice money.Centavos `json:"sellingPrice"`
	Seller       string         `json:"seller"`
	Unit         string         `json:"measurementUnit"`
	UnitMult     float64        `json:"unitMultiplier"`
}

type OrderItem

type OrderItem struct {
	ID       string         `json:"id"`
	SKU      string         `json:"sellerSku"`
	Name     string         `json:"name"`
	Quantity int            `json:"quantity"`
	Price    money.Centavos `json:"price"`
}

type PaymentSystem

type PaymentSystem struct {
	ID        int    `json:"id"`
	Name      string `json:"name"`
	GroupName string `json:"groupName"`
}

PaymentSystem is one payment method the store accepts. Discovered from the orderForm rather than hardcoded, because the set differs per store.

type PendingAuth

type PendingAuth struct {
	Email               string `json:"email"`
	AuthenticationToken string `json:"authenticationToken"`
}

PendingAuth records an in-flight access-code login. VTEX rejects a validate call whose authenticationToken came from a different start call, so the token has to survive between the two CLI invocations.

type SavedCard

type SavedCard struct {
	AccountID         string `json:"accountId"`
	CardNumber        string `json:"cardNumber"`
	Bin               string `json:"bin"`
	PaymentSystem     string `json:"paymentSystem"`
	PaymentSystemName string `json:"paymentSystemName"`
}

type SearchResult

type SearchResult struct {
	ProductID string         `json:"productId"`
	SKU       string         `json:"sku"`
	Name      string         `json:"name"`
	Price     money.Centavos `json:"price"`
	ListPrice money.Centavos `json:"listPrice"`
	Available int            `json:"available"`
	Seller    string         `json:"seller"`
	Unit      string         `json:"unit"`
	UnitMult  float64        `json:"unitMultiplier"`
}

SearchResult is one purchasable SKU.

Seller is carried per result rather than assumed from a constant: it is the value the cart API needs, and it differs per store (and in principle per item within a store).

type Session

type Session struct {
	AuthToken   string `json:"authToken"`
	OrderFormID string `json:"orderFormId"`
	Email       string `json:"email"`
}

Session is the storefront's view of the current visitor.

type Simulation

type Simulation struct {
	Items          []SimulationItem          `json:"items"`
	LogisticsInfo  []SimulationLogisticsInfo `json:"logisticsInfo"`
	PaymentSystems []PaymentSystem           `json:"paymentSystems"`
}

type SimulationItem

type SimulationItem struct {
	ID       string         `json:"id"`
	Quantity int            `json:"quantity"`
	Price    money.Centavos `json:"price"`
}

type SimulationItemRequest

type SimulationItemRequest struct {
	ID       string `json:"id"`
	Quantity int    `json:"quantity"`
	Seller   string `json:"seller"`
}

type SimulationLogisticsInfo

type SimulationLogisticsInfo struct {
	SLAs []SimulationSLA `json:"slas"`
}

type SimulationSLA

type SimulationSLA struct {
	Name                     string           `json:"name"`
	Price                    money.Centavos   `json:"price"`
	ShippingEstimate         string           `json:"shippingEstimate"`
	AvailableDeliveryWindows []DeliveryWindow `json:"availableDeliveryWindows"`
}

type Totalizer

type Totalizer struct {
	ID    string         `json:"id"`
	Name  string         `json:"name"`
	Value money.Centavos `json:"value"`
}

type TransactionResult

type TransactionResult struct {
	OrderGroup    string `json:"orderGroup"`
	TransactionID string `json:"transactionId"`
	ReceiverURI   string `json:"receiverUri"`
	MerchantName  string `json:"merchantName"`
}

type Wishlist added in v0.2.0

type Wishlist struct {
	Name   string         `json:"name"`
	Public bool           `json:"public"`
	Items  []WishlistItem `json:"items"`
}

type WishlistItem added in v0.2.0

type WishlistItem struct {
	ID        int    `json:"id"`
	ProductID string `json:"productId"`
	SKU       string `json:"sku"`
	Title     string `json:"title"`
}

WishlistItem is one saved product from the store's own wishlist.

ID is the item's position-derived identifier within the list, and it is what RemoveFromList takes — not the SKU. ProductID and SKU genuinely differ for products with variants, and AddToList wants both.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL