# Merchant Callback Each merchant may define a specific asynchronous HTTPS confirmation URL (callback URL) through which Payconiq notifies the status of a payment. This enables the merchant's or partner's backend to act upon the payment status (e.g., mark the payment in a database, update stock, send confirmation emails, etc.). Callbacks are asynchronous and issued via HTTP POST requests using TLS 1.2 encryption. For certain products (e.g., Top Up), a callback URL must be provided at the time of product creation. ## One-Way TLS Encryption Support In one-way TLS, Payconiq encrypts callback requests and validates the merchant's server certificate. No certificate exchange is needed beforehand. Callbacks should function out of the box. Contact: [devsupport@payconiq.be](mailto:devsupport@payconiq.be) for assistance. ## Callback Retry Policy Payconiq retries sending callbacks for up to **24 hours** if an HTTP 200 OK response is not received. Retry triggers include: * No response within 15 seconds * HTTP 429 Too Many Requests * HTTP 500 Internal Server Error * HTTP 503 Service Unavailable * HTTP 504 Gateway Timeout * HTTP 509 Bandwidth Limit Exceeded **Notes:** * The payment status does not change. * The callback content (headers, body, target URL) remains identical. * Payconiq stops retrying after a 200 OK or after 24 hours. ## Callback Headers Callback requests contain several headers, including: ```http signature: content-type: application/json user-agent: Payconiq Payments/v3 ``` | Name | Description | | --- | --- | | `signature` | A JSON Web Signature (JWS) in base64url format, digitally signed by Payconiq. | | `user-agent` | Identifies the Payconiq callback sender. | | `content-type` | Indicates the media type of the payload (application/json). | ## Callback Signature To verify Payconiq-generated callbacks, use the detached [JSON Web Signature (JWS)](https://tools.ietf.org/html/rfc7797) sent in the `signature` header. The JWS includes: * JOSE Header (base64url encoded) * JWS Payload (not included) * JWS Signature ```text jws = base64URLEncode(JOSE Header)..base64URLEncode(Signature(base64URLEncode(JOSE Header) + base64URLEncode(Request Body))) ``` ### JOSE Header Example ```json { "typ": "jose+json", "kid": "JWK kid", "alg": "ES256", "crit": ["https://payconiq.com/sub", "https://payconiq.com/iss", "https://payconiq.com/iat", "https://payconiq.com/jti", "https://payconiq.com/path"], "https://payconiq.com/sub": "{PaymentProfileId}", "https://payconiq.com/iss": "Payconiq", "https://payconiq.com/iat": "{ISO 8601 UTC Timestamp}", "https://payconiq.com/jti": "{Unique-request-identifier}", "https://payconiq.com/path": "https://www.merchantcallback.com/payconiqpayment" } ``` ### Signature Verification Steps 1. Cache the JWKS from Payconiq. 2. Extract `kid` from JOSE header. 3. Match `kid` with cached JWK: * If matched, verify signature using your preferred library (e.g., jose4j for Java). * Ensure all `crit` headers are present and valid. 4. If not matched, fetch and re-cache the JWKS, then repeat step 3. ## Callback Body The body contains JSON with payment status details. Verify the signature before processing this data. ## Sample Request – `callback` ## Certificates Payconiq publishes its public keys in JWKS format: * **PREPROD JWK**: jwks.preprod.bancontact.net * **PROD JWK**: jwks.bancontact.net ### Certificate Rotation * Bancontact Payconiq may rotate its certificate without prior notice. * Merchants who pin certificates must pin only the CN name of the certificate, enabling seamless rotation. * A new JWK will be added for 24 hours before the old one is removed. * Merchants should cache JWKs for up to 12 hours and re-fetch if verification fails.