Custom Payment Gateway
This guide shows how to connect your own payment gateway to vivenu checkout, refund, and recurring-payment flows.
For example implementations, request/response models, and signature verification, see Integrate Payment Gateway.
Prerequisites
- Create a gateway in Payment Gateways.
- Copy the gateway secret from The payment gateway object.
- Integrate your payment gateway as described below, then activate it via Update a payment gateway.
Payment flow
-
Customer selects your gateway in checkout.
-
Customer is redirected to the URL defined when the gateway was created.
When paying online with a saved method, that URL includes a
customerPaymentMethodTokenquery parameter. Use the stored payment method and do not collect new payment details. -
You verify and process the payment.
-
You confirm or fail the payment request against vivenu, then redirect the customer to the matching return URL.
If the customer already paid and the /confirm request fails, refund the amount.
See the full endpoint details in Payment Requests.
Refund flow
When refunds are enabled, expose a POST route and set it on the payment gateway. vivenu sends a signed refund request payload to that endpoint, including an x-vivenu-signature header.
In case of partial refunds the amount can be lower than the initial amount of the payment.
Always verify the signature to prevent malicious users from sending refund requests.
Refund request payload
Required attributes
- Name
id- Type
- string
- Description
A unique ID for the request
- Name
time- Type
- string date-time
- Description
An ISO timestamp of the request. Can be used to prevent old requests from being processed
- Name
mode- Type
- enum(dev, prod)
- Description
Server mode of the API
- Name
type- Type
- enum(payment.refund)
- Description
The type of the action
- Name
data- Type
- object
- Description
Required nested attributes (5)
- Name
transactionId- Type
- string
- Description
The ID of the transaction to refund
- Name
sellerId- Type
- string
- Description
The ID of the seller
- Name
psp- Type
- string
- Description
The reference of the payment
- Name
amount- Type
- number float
- Description
The amount to refund
- Name
currency- Type
- enum(EUR, USD, GBP, AUD, CHF, THB, ILS, COP, MXN, DKK, NOK, SEK, QAR, CAD, ISK, GTQ, INR, DOP, SGD, PLN, SAR, TTD, ZAR, KYD, HKD, CZK, KRW, JPY, NZD, AED, MAD, TWD, BRL, BWP, NAD, KES, SCR, TRY, SZL, LSL, TZS, UGX, ZMW, ZWG, GHS, NGN, SLE, LRD, XOF, XAF, GEL, IDR, ARS, CRC, HUF, EGP, MYR, VND, PHP, MWK)
- Description
An ISO 4217 3-character code of the currency
Example
{
"id": "507f191e810c19729de860ea",
"time": "2030-01-23T23:00:00.123Z",
"mode": "dev",
"type": "payment.refund",
"data": {
"transactionId": "507f191e810c19729de860ea",
"sellerId": "507f191e810c19729de860ea",
"psp": "string",
"amount": 19.15,
"currency": "EUR"
}
}Refund response payload
Optional attributes
- Name
reference- Type
- string
- Description
A reference for the refund, e.g. a PSP transaction ID. Defaults to original refund request ID
- Name
error- Type
- enum(amount_too_high, amount_too_low, payment_already_refunded, payment_not_refundable, insufficient_account_balance, payment_disputed, partial_refunds_not_supported, payment_too_old)
- Description
The error code. If present, the refund is considered failed.
Example
{
"reference": "string",
"error": "amount_too_high"
}Charge payment method flow
To allow users to save payment methods and use them for recurrent payments such as subscriptions or payment plans, support setup requests on your pay endpoint, and expose an additional POST charge route on the payment gateway. Enable Recurrent payments in the gateway settings as well.
The following changes are required from your gateway:
-
Save a payment method (setup)
The customer adds a payment method in their account and chooses your custom gateway. They are redirected to your pay endpoint with a payment request whose
originis"setup". Collect the payment method details, then confirm the request viaPOST /api/payments/requests/{id}/confirmwithpaymentMethodIdentifierand optionalpaymentMethodExpiration. The response includes acustomerPaymentMethodToken— store it together with the payment credentials — and asuccessReturnUrlto redirect the customer back. -
Charge a saved payment method
When the customer pays with a saved method, we
POSTa charge request to your charge endpoint. The payload includes the samecustomerPaymentMethodToken. Use thex-vivenu-signatureheader to verify that the request is authentic and signed with your gateway secret, look up the stored credentials, and charge the payment method. -
Online payments with saved payment method
The pay endpoint needs to accept a
customerPaymentMethodTokenquery parameter. When provided, the payment page should not allow the user to enter their payment details, but instead should use previously saved payment method details associated with the token.This flow can be used if re-authorization is needed, for example if the issuer requires 3DS or similar online re-authorization for a payment method.
Security recommendations
- Never pass sensitive credentials like full credit card numbers or bank account numbers to the confirm endpoint. For safety reasons, we will only store the last 4 characters of any identifier you pass.
- Always verify that the provided
customerPaymentMethodTokenandcustomerIdmatch. This prevents abuse if an attacker stealscustomerPaymentMethodTokenfrom the user, ascustomerIdstored in payment requests cannot be forged. - Always verify the
x-vivenu-signatureheader on refund and charge requests. See Verify request signature.
Charge request payload
Required attributes
- Name
id- Type
- string
- Description
A unique ID for the request
- Name
time- Type
- string date-time
- Description
An ISO timestamp of the request. Can be used to prevent old requests from being processed
- Name
mode- Type
- enum(dev, prod)
- Description
Server mode of the API
- Name
paymentId- Type
- string
- Description
The ID of the payment request to charge
- Name
customerPaymentMethodToken- Type
- string
- Description
The token of the customer payment method to charge
Example
{
"id": "507f191e810c19729de860ea",
"time": "2030-01-23T23:00:00.123Z",
"mode": "dev",
"paymentId": "507f191e810c19729de860ea",
"customerPaymentMethodToken": "string"
}Charge response payload
Optional attributes
- Name
reference- Type
- string
- Description
A reference for the charge, e.g. a PSP transaction ID. Defaults to original charge request ID
- Name
error- Type
- enum(authentication_required, authorization_expired, authorization_revoked, insufficient_funds, card_blocked, card_expired, suspected_fraud, invalid_amount, purchase_type_unsupported)
- Description
The error code. If present, the payment is considered failed.
Example
{
"reference": "string",
"error": "authentication_required"
}Verify request signature
Validate x-vivenu-signature by hashing the raw request body with sha256 and your gateway secret. Always verify this header on every refund and charge request your gateway receives.
const signature = crypto
.createHmac('sha256', GATEWAY_SECRET)
.update(req.rawPayload)
.digest('hex')
const requestSignature = req.headers['x-vivenu-signature']
const isValid = signature.toLowerCase() === requestSignature.toLowerCase()