If you are either a sender or a receiver of RippleNet payments, you can use webhooks to receive notifications from RippleNet about changes to the status of your RippleNet payments, rather than having to keep polling for updates.
This page provides an overview of how to use webhooks with RippleNet payments.
A webhook is a method by which a service can notify a client application of relevant events, by sending notification messages to a callback URL that the client has registered with the service. When the service completes a task or encounters an error, it sends a notification to the specified callback URL — using the HTTP POST method — to let it know that information is available about the task or error. This saves the client from having to continuously poll the service for new information.
While there are several variations on secure webhook authentication — including shared tokens, and HMAC (hash-based message authentication code) signatures — RippleNet supports a thin-payload approach.
In the thin-payload approach, the server sends a tiny payload — containing no information except a Message ID — to the callback URL when it has new information about a task or event. The client application then sends a request to the application server to retrieve the full notification details for that Message ID.
The benefit of this approach is that regardless of whether authentication is performed at the time of the thin-payload delivery, the client only receives the full notification when it sends a regular authentication request to the web API. The thin-payload approach also offers less of a programming burden on the client application developers than the HMAC approach.
This section is for any details that you need to take care of before using webhooks with the RippleNet orchestrated payments.
At the time you onboard with RippleNet, you need to provide a public URL that is both accessible over the internet, and restricted for access. This URL is configured in the RippleNet instance for your client application.
Contact your Ripple representative to register your webhook callback URL.
To ensure that webhook callbacks originate from RippleNet, you may need to add the RippleNet IP addresses to your server’s allowlist.
Contact your CPE for a list of IP addresses to add to your allowlist.
If you are a sender of RippleNet payments, there are two things you need to do to receive webhook notifications about your payments.
- You must register a callback URL that RippleNet can post to when there is a notification available. The callback URL needs to be an HTTPS URL (not HTTP) with a public key certificate. Contact your Ripple CPE to register your webhook callback URL.
- Your client application must use the basic payment flow API operations for creating and processing payments. When you use the Create orchestration payment or Accept orchestration payment operation to initiate a new RippleNet payment, its actions trigger the notifications via webhook from the RippleNet server.
Note that it is not necessary for the receiver to use the basic payment flow API operations, for you, as sender, to receive webhook notifications. As long as your webhook callback URL is registered with RippleNet, and as long as you are using the basic payment flow API operations (Create orchestration payment or Accept orchestration payment) to initiate payments, then you will receive webhook notifications about changes to the status of your payments.
If you are a receiver of RippleNet payments, there are two things you need to do to receive webhook notifications about payments addressed to you.
- You must register a callback URL that RippleNet can post to when there is a notification available. The callback URL needs to be an HTTPS URL (not HTTP) with a public key certificate. Contact your Ripple CPE to register your webhook callback URL.
- When you process payments — specifically, when you lock and complete payments — you must use the Post action to orchestration payment operation, which defines the basic payment flow for receivers, instead of the equivalent API operations such as Lock payment and Complete payment, which are not webhook-enabled. The actions trigger the notifications via webhook from the RippleNet server.
Note that it is not necessary for the sender to use webhook-enabled API operations (specifically, the basic payment flow for senders), for you, as receiver, to receive webhook notifications. As long as your webhook callback URL is registered with RippleNet, and as long as you are using the Post action to orchestration payment operation, which defines the basic payment flow for receivers, then you will receive webhook notifications about changes to the status of payments relevant to you.
For both senders and receivers, once you have registered your webhook callback URL, and as long as you are using the webhook-enabled API operations described above, any change to the status of a RippleNet payment that is relevant to you triggers RippleNet to send a notification to your callback URL.
The notification to your callback URL will be in the form of an HTTP POST with a JSON body containing a message ID. This is the message ID for the full notification message. Here is an example.
{
"msg_id": "407ad2d7-6a8d-46de-820a-487bdf9aa0fb"
}Upon receiving the notification, your callback application should respond with HTTP status code 200. This stops the RippleNet server from retrying the callback. If the RippleNet server does not get a response, or if the response is anything other than a status in class 2xx (success), it retries every 5 minutes, for a maximum of 12 retries.
Your application should be able to handle the case of duplicate notifications, in case RippleNet fails to receive the 200 response and resends the notification.
Once your application has the message ID for the notification message, you can pass this message ID to the Get orchestration notification operation, to get the full details of the notification.
GET /v4/orchestration/payment/notification/407ad2d7-6a8d-46de-820a-487bdf9aa0fb HTTP/1.1
Host: aclient.i.ripple.com
Content-Type: application/json
Authorization: Bearer <token>The response of the Get orchestration notification operation contains the details of the notification message.
{
"uuid": "407ad2d7-6a8d-46de-820a-487bdf9aa0fb",
"notification_type": "PAYMENT_SUCCESS",
"notification_version": "1.0",
"notification_status": "NEW",
"notification_payload": {
"sender_end_to_end_id": "19999999999-012",
"payment_id": "ab2d66c9-e67a-4020-b0c9-c249912a07a0",
"payment_status": "COMPLETED",
"previous_payment_status": "PREPARED",
"connector_role": "SENDING",
"payment_type": "REGULAR",
"payout_method": null,
"original_sender_end_to_end_id": null,
"output": null
},
"created_at": "2021-09-03T12:30:22.081Z",
"modified_at": "2021-09-03T12:30:22.081Z"
}When the RippleNet server calls your webhook URL to send the notification to your application, if the application is not available or unresponsive, or if it responds with any status code other than 200 (or some other 2xx status code), the RippleNet service retries the notification every 5 minutes — for a maximum of 12 retries.
- Add the RippleNet IP addresses to the allowlist for your server handling the webhook callback URL, to ensure that events are coming from trusted sources. Contact your CPE for the list of IP addresses to add.
- Your application must respond to the notification immediately using status
200, and process the notification asynchronously in a separate thread. - Your client application code should be resilient to handle duplicate notifications. The RippleNet server may send duplicate notifications it sends a notification to your callback URL, but fails to get a success response.
Here is example code in Java for async processing:
//Customer webhook controller receives callback notification ROS server
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> callbackNotification(@RequestBody @Valid CallbackMessage callbackMessage) {
notificationService.handleCallbackNotification(callbackMessage);
return ResponseEntity.ok(callbackMessage.toString());
}
//customer middleware controller code - may write similar code as shown below
//Save callback event to database
public void handleCallbackNotification(CallbackMessage callbackMessage) {
logger.info("Callback notification received: " + callbackMessage);
//Register event notification in DB with message id and trigger async message processing
EventDTO event = new EventDTO();
event.setMessageId(callbackMessage.getMsgId());
event.setEventStatus(EventStatus.READY);
eventService.registerEvent(event);
//call below function to trigger async processing of notification and return.
this.startAsyncNotificationProcessing(callbackMessage.getMsgId());
}
//Start asynchronous processing of notification
public void startAsyncNotificationProcessing(UUID msgId) {
CompletableFuture.runAsync(() -> {
try {
//calling ROS API to get details of the message
NotificationResponse response = rosApi.getOrchestrationPaymentNotificationByUUID(msgId);
logger.info("Async message processing started for message id: {}.", msgId);
//Write logic to handle message type and change event status to COMPLETED in their DB
externalOutProcessor.process(response.getNotificationType(), msgId,objectMapper.writeValueAsString(response.getNotificationPayload()));
logger.info("Async message processing finished for message id: {}.", msgId);
} catch (Exception e) {
logger.error("Exception occurred while trying to process message async ", e);
}
}, executorService);
}