Nepting ePay v2 demo brief for coding agents Goal - Build a single full-stack demo app for Nepting ePay redirect flow. - Keep signing server-side only. Never expose the secret key in browser code. - Main outcome: a test page that can submit a payment request to Nepting qualif, then show browser callbacks and optional server-to-server notifications. Default qualification config - brandId=102 - merchantId=992781110633 - secretKey=01234567890 - paymentUrl=https://qualif.nepting.com/epay/payment Suggested env vars - EPAY_BRAND_ID - EPAY_MERCHANT_ID - EPAY_SECRET_KEY - EPAY_PAYMENT_URL Recommended app shape - GET / : render the test form - POST /epay/checkout : build payload, encode fields, sign, return auto-submitting HTML form to Nepting - GET or POST /epay/returns/success : capture callback, verify signature, render result - GET or POST /epay/returns/error : same - GET or POST /epay/returns/refused : same - GET or POST /epay/returns/cancel : same - POST /epay/status : capture server-to-server notification, verify signature, return 204 - Optional GET /epay/status : debug endpoint returning {"status":"true"} HTTP flow 1. Merchant server prepares request fields. 2. Merchant server Base64-encodes all alpha/string fields. 3. Merchant server computes request signature on encoded values. 4. Browser submits a POST form to https://qualif.nepting.com/epay/payment 5. Nepting shows its hosted payment page. 6. Nepting redirects browser to success/error/refused/cancel URL. 7. Optional: Nepting POSTs to urlStatus. Important rule - "payload" = POST body sent to /epay/payment. Request encoding - Encode alpha/string fields in Base64 UTF-8. - Keep numeric / flag fields plain. Alpha fields commonly needed - brandId - merchantId - apiVersion - transactionId - transactionType - merchantLabel - merchantPrivateData - reservationId - cardHolderEmail - cardHolderHomePhone - cardHolderMobilePhone - cardHolderWorkPhone - billingAddress - billingZipCode - billingCity - billingState - billingCountry - shippingAddress - shippingZipCode - shippingCity - shippingState - shippingCountry - currencyAlpha - urlSuccess - urlError - urlRefused - urlCancel - urlStatus - locale - description - threedsChallengeIndicator Numeric / plain fields commonly needed - amount - currencyCode - currencyFraction - merchantDateTime - displayMerchantLabel - enrolment - partialAmountEnabled - statusPage - urlStatusMode Request signature - Concatenate fields in this order, skipping missing optional fields: merchantId | transactionId | amount | currencyCode | urlSuccess | urlError | urlRefused | urlCancel | urlStatus | mopId - Use encoded values for alpha fields. - Append secretKey after the last pipe-separated field. - Compute SHA-256 over the UTF-8 source string. - Output digest in Base64. Browser callback signature (v2) - merchantId | transactionId | result | secretKey - Verify on received values before decoding anything for display. Working baseline request - Treat these as required: brandId merchantId merchantLabel apiVersion=2.0 transactionId amount currencyCode=978 urlSuccess urlError urlRefused signature Recommended richer baseline - Minimal payloads were accepted by the algorithm but still failed in real qualif tests. - Use this richer baseline for the first smoke test: transactionType=debitALivraison currencyAlpha=EUR currencyFraction=2 merchantDateTime=YYYYMMDD-HHmmss locale=fr statusPage=0 urlCancel= cardHolderEmail=dev@nepting.com cardHolderHomePhone=33-600050000 cardHolderMobilePhone=33-600050000 cardHolderWorkPhone=33-600050000 billingAddress=18 rue auguste comte billingZipCode=34000 billingCity=Montpellier billingState=OCC billingCountry=250 shippingAddress=18 rue auguste comte shippingZipCode=34000 shippingCity=Montpellier shippingState=OCC shippingCountry=250 Optional fields used in a working request - displayMerchantLabel=1 - enrolment=1 - partialAmountEnabled=1 Recommended first test values - amount=5000 - statusPage=0 - do not send urlStatus at first Example raw request values before Base64 { "brandId": "102", "merchantId": "992781110633", "merchantLabel": "Planet Monetic ePay Test", "apiVersion": "2.0", "transactionId": "PM202603290001", "transactionType": "debitALivraison", "amount": "5000", "currencyCode": "978", "currencyAlpha": "EUR", "currencyFraction": "2", "merchantDateTime": "20260329-151611", "locale": "fr", "urlSuccess": "https://merchant.example/epay/returns/success", "urlError": "https://merchant.example/epay/returns/error", "urlRefused": "https://merchant.example/epay/returns/refused", "urlCancel": "https://merchant.example/epay/returns/cancel", "cardHolderEmail": "dev@nepting.com", "cardHolderHomePhone": "33-600050000", "cardHolderMobilePhone": "33-600050000", "cardHolderWorkPhone": "33-600050000", "billingAddress": "18 rue auguste comte", "billingZipCode": "34000", "billingCity": "Montpellier", "billingState": "OCC", "billingCountry": "250", "shippingAddress": "18 rue auguste comte", "shippingZipCode": "34000", "shippingCity": "Montpellier", "shippingState": "OCC", "shippingCountry": "250" } urlStatus rules - Keep disabled until the endpoint is public and registered with Nepting. - POST /epay/status must respond fast, ideally under 3 seconds. - Preferred response: 204 No Content. - Accepted alternative: 2xx with Content-Type: application/json and body {"status":"true"}. - Do not return 302, HTML, or arbitrary plain-text 200 responses. Troubleshooting - Immediate redirect to urlError before payment page usually means one of: wrong merchant/app activation in qualif wrong Base64 encoding on alpha fields signature built from raw instead of encoded values missing merchantLabel payload too minimal urlStatus enabled too early - "Ticket non disponible" is not necessarily root cause. Inspect result and extendedResult first. Implementation constraints - One app is enough. Separate front-end and back-end projects are not required. - Any stack works if it can render HTML, do server-side signing, and expose callback routes. - SvelteKit is a good fit for a single-app demo. Minimal implementation checklist - Build a form page with editable amount / transactionId / optional fields. - Generate transactionId server-side or prefill it. - Generate merchantDateTime server-side if left empty. - Build encoded payload server-side. - Sign server-side. - Auto-submit hidden HTML form to Nepting. - Record callback payloads for debugging. - Decode Base64 values only for display/debug, not for signature verification.