Webhooks

If you are either a sender or a receiver of RippleNet payments, it is a recommended best practice to use webhooks to receive notifications from RippleNet about changes to the status of your RippleNet payments, rather than repeatedly polling for updates.

This topic provides an overview of how to use webhooks with RippleNet payments.

Introduction — What is a webhook?

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.

Thin-payload webhooks

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 only 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.

Onboarding

This section describes prerequisites for using webhooks.

Register your callback URL

At the time you onboard with RippleNet, you need to provide a callback URL that RippleNet can post to when there are notifications available. This must be a public URL that is both accessible over the internet, and restricted for access. The callback URL needs to be an HTTPS URL (not HTTP) with a public key certificate. Contact your CPE to register your webhook callback URL. This URL is configured in the RippleNet instance for your client application.

To register your webhook callback URL, contact your Customer and Partner Engineer (CPE).

Add RippleNet IP addresses to your allowlist

To ensure that webhook callbacks originate from RippleNet, you may need to add the RippleNet IP addresses to your server’s allowlist.

For a list of IP addresses to add to your allowlist, contact your Customer and Partner Engineer (CPE).

Use webhooks as a sender

If you are a sender of RippleNet payments, there are two things you need to do to receive webhook notifications about your payments.

  1. You must register a callback URL , as described above.
  2. Your client application must use the orchestration API operations — Create orchestration payment or Accept orchestration payment — for initiating payments. When you use the orchestration operations to initiate a new RippleNet payment, they trigger the notifications through webhooks from the RippleNet server.
Note

It is not necessary for the receiver to use the webhook-enabled 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 orchestration 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.

Use webhooks as a receiver

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.

  1. You must register a callback URL , as described at the top of this topic.
  2. When you process payments — specifically, when you lock and complete payments — you must use the Post action to orchestration payment operation. The actions trigger the notifications via webhook from the RippleNet server. Please note that the Lock payment and Complete payment API operations are not webhook-enabled.
Note

It is not necessary for the sender to use webhook-enabled API operations 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, you will receive webhook notifications about changes to the status of payments relevant to you.

Process webhook notifications

For both senders and receivers, once you have registered your webhook callback URL, and as long as you use 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, which is the message ID for the full notification message.

Example:

Copy
Copied!
{
    "msg_id": "407ad2d7-6a8d-46de-820a-487bdf9aa0fb"
}

Respond to the notification

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.

Note

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.

Get the full notification details

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.

Copy
Copied!
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.

Copy
Copied!
{
       "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"
}

Webhook retries

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.

Best practices for webhooks integration

To summarize the best practices for integrating webhooks:

  1. To ensure that events are coming from trusted source, your RippleNet IP addresses must be added to the allowlist of your server handling the webhook callback URL. For the list of IP addresses to add, contact your CPE.
  2. Your application must respond to the notification immediately using status 200 and process the notification asynchronously in a separate thread.
  3. Your client application code should be resilient to handle duplicate notifications. The RippleNet server may send duplicate notifications, if it sends a notification to your callback URL, but fails to get a success response.

Example Java code

Here is example code in Java for async processing:

Copy
Copied!
  //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);
    }