9x Paynet OpenAPI

Authentication

Morph 1 app RSA2; morph 2 Access Key HMAC

OpenAPI authentication has two layers, stacked by app configuration.

Morph 1 — app RSA2 (always)

Every request must set sign using the app private key.

Canonical string

  1. Take all non-empty body fields
  2. Remove sign itself
  3. Keep sign_type=RSA2
  4. Sort keys lexicographically, join as k1=v1&k2=v2&…

Sign

SHA256WithRSA (PKCS#1 v1.5) over that string, Base64-encode into sign.

Re-sign whenever the body changes. Keep the private key on your server only.

Morph 2 — Access Key HMAC (when enabled)

If the app requires Access Keys (access_key_required), payment methods must also send:

FieldMeaning
key_idAccess Key id
key_signHMAC signature (Base64)

Computing key_sign

mac_key  = SHA-256( utf8(secret) )     // 32 bytes — do not HMAC with raw secret
content  = sort_join(app_id, key_id, merchant_no, method, store_no, timestamp)
key_sign = Base64( HMAC-SHA256(mac_key, content) )

sort_join: non-empty fields only, keys sorted, k=v joined with &. Do not include key_sign in content.

Exempt from morph 2

access.key.* (create / list / rotate / revoke) uses morph 1 only.
Managing keys must not require an Access Key (chicken-and-egg).

How the layers run

request
  → verify app RSA2 (reject on failure)
  → if app requires Access Key and method is not access.key.*
        → verify key_id / key_sign / binding / scope
  → business logic

Without the force flag, payments may use morph 1 only (early integration). Once forced, a missing key yields errors such as E07311. See Errors.

On this page