Skip to content

Configuration

Amir Iranmanesh edited this page Jul 31, 2026 · 2 revisions

Configuration

payvand.Config is one struct for every provider. Each gateway validates the fields it needs inside New, so a misconfigured terminal fails when you wire it rather than when a customer pays.

type Config struct {
	MerchantID  string            // merchant / business identifier
	TerminalID  string            // terminal or acceptor identifier
	Username    string            // terminal user name
	Password    string            // terminal password
	MerchantKey string            // API key, bearer token or private key
	IBAN        string            // settlement account, for multiplexing gateways
	Extra       map[string]string // anything provider specific
}

Mapping

Gateway MerchantKey MerchantID TerminalID Username Password IBAN
Zarinpal merchant id (36 chars)
Zibal merchant
Vandar API key business name (refunds only)
PayWeb bearer token
IDPay API key
Pay.ir API key
NextPay API key
PayPing bearer token
BitPay.ir API key
YekPay merchant id
Sadad · Bank Melli base64 terminal key merchant id terminal id
Parsian login account (pin) settlement IBAN
Iran Kish acquirer RSA public key terminal id acceptor id terminal password
Mellat terminal id user name password
Saman · SEP terminal number
Pasargad RSA private key merchant code terminal code
AsanPardakht merchant configuration id usr header pwd header
Sepehr · Bank Saderat terminal id
TOP EShop pin
Virtual

Notes per gateway

SadadMerchantKey is the base64 terminal key, used to build the 3DES signature of every call. It is not the merchant id.

Iran KishMerchantKey holds the acquirer's RSA public key (PEM). TerminalID and Password must be hexadecimal strings, because the protocol concatenates and hex-decodes them while building the authentication envelope.

PasargadMerchantKey is the RSA private key. Both a PEM block (PKCS#1 or PKCS#8) and the .NET <RSAKeyValue> XML that Pasargad still distributes are accepted, so you can paste whichever the panel gave you. Pasargad also requires the invoice date of the purchase at verification time; it is returned in PurchaseResponse.Extra[pasargad.InvoiceDateKey] — persist it with the order.

Vandar — refunds go through the business API, which needs MerchantID (the business name) and usually a bearer token, set with vandar.WithAccessToken.

ParsianIBAN is only needed when you enable settlement to an IBAN with parsian.WithSettlementToIBAN or pass explicit shares.

AsanPardakhtUsername and Password are sent as the usr and pwd headers, not as a body field.

Zibal / Pay.ir — both have a reserved sandbox identity, selected with payvand.WithSandbox(true): Zibal switches the merchant to zibal, Pay.ir switches the API key to test.

IDPay — the sandbox is a header (X-SANDBOX: 1), also driven by payvand.WithSandbox(true).

Loading from the environment

cfg := payvand.Config{
    MerchantKey: os.Getenv("PAY_MERCHANT_KEY"),
    MerchantID:  os.Getenv("PAY_MERCHANT_ID"),
    TerminalID:  os.Getenv("PAY_TERMINAL_ID"),
    Username:    os.Getenv("PAY_USERNAME"),
    Password:    os.Getenv("PAY_PASSWORD"),
    IBAN:        os.Getenv("PAY_IBAN"),
}

gw, err := pv.Gateway(payvand.Name(os.Getenv("PAY_GATEWAY")), cfg)

Unknown names return payvand.ErrGatewayNotRegistered, so a typo in the configuration fails loudly at start-up.

Several terminals at once

Nothing is global. Build one gateway per terminal and keep them in a map:

type terminal struct {
    Gateway payvand.Name
    Config  payvand.Config
    Options []payvand.Option
}

gateways := map[string]payvand.Gateway{}
for id, t := range terminals {
    gw, err := pv.Gateway(t.Gateway, t.Config, t.Options...)
    if err != nil {
        return fmt.Errorf("terminal %s: %w", id, err)
    }
    gateways[id] = gw
}

Keeping credentials safe

  • Never commit terminal keys. The repository .gitignore already excludes *.pem, *.key, *.p12 and keys/.
  • PurchaseResponse.Raw, VerifyResponse.Raw and the logger receive provider payloads; redact them before they reach a log aggregator.
  • Rotate a key by rebuilding the gateway — nothing is cached between calls.

Next: Options · Supported Gateways

Clone this wiki locally