External Payment Plugin
Last updatedExternal payment plugin allows you to integrate Payment Service Providers of your choice that are not supported by Centra. It is intended to be used along with Checkout API, however requests finalizing payments should be handled server-side as payload signature using shared secret is required.
Setup#
External payment plugin settings look like this:
To set up External Payment Plugin you need to provide all the basic plugin information like Name, Name in Frontend, URI and:
-
Notification key - auto-generated value used to authorize authorization and capture notifications to endpoint visible under
Notifications URL
. Must be stored server-side and not revealed to third parties. -
Shared secret - auto-generated value used to sign payload send to endpoints finalizing the payment when External Payment Plugin is used. Must be stored server-side and not revealed to third parties.
Flow#
The integration with Payment Service Provider, order creation and management must be done outside of Centra. Results of payment authorization and capture from redirects and push notifications should be forwarded to Centra to proper endpoints.
-
Customer goes to checkout. Centra API gets a
GET /selection
-
external-payment
method is found and can be selected for checkout -
POST /payment
request is made with"paymentMethod": "external-payment"
which on success responds with following data:
1
2
3
4
5
{
"token": "abcd1234efgh12340ba6142228334aaf4",
"action": "external",
"selection": "4f1211119567211c441d86e19fbd7114"
}
You should store the selection
field value. It needs to be included in signature payload when finalizing the payment.
At the same time you will most probably initiate the payment session with Payment Service you're integrating, so you should associate the selection id from Centra
with payment session identifier from Payment Service.
1
2
//this will be needed to finalize the order
[paymentSessionIdentifier, selectionId]
Order finalization#
- Redirect
When user finalizes the payment in html widget and gets redirected to the success page you will send data provided by Payment Service back to your backend so that it can be signed and forwarded to Centra's payment-result endpoint. At this point you should use the value pair stored before to map payment result you've obtained from Payment Service to its associated selection id:
1
[paymentSessionIdentifier, selectionId]
Sign the payload and send a POST /payment-result
(as shown in details below).
- Authorisation push notification
Authorisation result will be also send to your backend by Payment Service through webhook or so-called push notification. Here you should also use value pair:
1
[paymentSessionIdentifier, selectionId]
to trace back selection id from paymentSessionIdentifier. You should forward this request to Centra push notification endpoint (details below).
There is no way to provide or update the customer address using requests finalizing the payment. Centra needs to know the customer address before. Not providing the address before will result in invalid orders with empty address.
Captures#
Captures must be handled outside of Centra within your own integration with Payment Service. Result of capture should be sent towards push notification endpoint using signed request with intent=capture
.
This endpoint is intended for receiving authorization information. It can be called only once with successful authorization per order.
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"paymentMethodFields": {
"selection": "selection",
"signature": "signature",
"currency": "SEK",
"amount": "100.00",
"timestamp": 1627029828,
"transactionReference": "transactionReference",
"success": true,
"transaction": {
"key": "value"
}
}
}
Field | Type | Comment |
---|---|---|
selection | string | Selection id returned at POST /payment call |
signature | string | Base64 encoded signed payload (details below) |
currency | string | Currency code (ISO 4217) |
amount | string | Numeric string with dot as decimal separator |
timestamp | int | Signature unix timestamp in UTC. Must be provided in seconds. The value is validated so you need to provide the current timestamp each time you send a request. |
transactionReference | string | Transaction identifier from PSP |
success | boolean | Successful or failed result of payment authorization |
transaction | object | All the transaction details that were received from PSP |
Signature
The signature is a base64 encoded HMAC SHA256 hash. Shared secret is configurable in External Payment Plugin settings in Centra AMS. Browser snippet using JavaScript and CryptoJS library:
1
btoa(CryptoJS.HmacSHA256(payload, secret).toString(CryptoJS.digest));
Node snippet using popular npm package crypto-js
:
1
2
3
let hashedSignature = HmacSHA256(str, secret); //CryptoJS.lib.WordArray
let hashedSignatureHex = hashedSignature.toString(); //hex encoded string
let base64encodedSignature = Buffer.from(hashedSignatureHex).toString('base64'); //base64 encoded signature
Signature payload fields
Signature payload fields must be provided in following order, separated by colon:
- selection id (received in
POST /payment call
) - amount
- currency
- timestamp
- transactionReference
- success
payload: selectionId:amount:currency:timestamp:transactionReference:success
Response:
On success=true
it will respond with HTTP status 201 and order object. The order will be created in Centra backend. (note: only one such call per order is allowed)
On success=false
Centra will store the information about failed authorization and will respond with HTTP status 412. The order is not created yet.
example error response:
1
2
3
4
5
6
7
8
9
{
"token": "123412341234b11b35328200afd1234",
"errors": {
"paymentMethod": "failed"
},
"messages": [
"Mismatched currency: USD, basket currency: SEK"
]
}
Request:
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"selection": "selection",
"signature": "signature",
"currency": "SEK",
"amount": "100.00",
"timestamp": 1627029828,
"transactionReference": "transactionReference",
"success": true,
"intent": "auth",
"transaction": {
"key": "value"
}
}
Field | Type | Comment |
---|---|---|
selection | string | Selection id returned at POST /payment call |
signature | string | Base64 encoded signed payload (details below) |
currency | string | Currency code (ISO 4217) |
amount | string | Numeric string with dot as decimal separator, e.g. "100.00" |
timestamp | int | Signature unix timestamp in UTC |
transactionReference | string | Transaction identifier from PSP |
success | boolean | Successful or failed result of payment authorization |
intent | string | Intent of a notification, possible values: auth/capture |
transaction | object | All the transaction details that were received from PSP |
Signature
The signature is a base64 encoded HMAC SHA256 hash. Example code using JavaScript and CryptoJS library:
1
btoa(CryptoJS.HmacSHA256($payload, secret).toString(CryptoJS.digest));
Signature payload fields
Signature payload fields must be provided in following order, separated by colon:
- selection id (received in
POST /payment call
) - amount
- currency
- timestamp
- transactionReference
- success
- intent
payload: selectionId:amount:currency:timestamp:transactionReference:success:intent
Response:
If the push notification is accepted Centra will respond with HTTP status 200.
Example response:
1
2
3
4
{
"success": true,
"message": "OK"
}
Status other than 200 indicates that something went wrong. Either the sent data is corrupted or other error occured like some fields missing or invalid signature. This may result in payments not visible in Centra and orders not being accepted. The message field of response object will contain the failure reason.
Example response:
1
2
3
4
{
"success": false,
"message": "Invalid intent: test"
}
Only one successful (success=true) authorization and one successful (success=true) capture is allowed per order.
Captures and refunds:#
Captures and refunds should be handled outside of Centra. Captures and refunds triggered by Order API or AMS are forbidden for orders paid with External Payment Plugin and will result in following error:
- Capturing shipments or trying to create refund via creating return in Order API are also not allowed for orders paid with External Payment Plugin:
1
2
3
4
5
{
"status": "no",
"msg": "Action not supported by external payment plugin. Please do that action in your payment provider.",
"order": 123
}