On-us via CSM determination

This page explains how to customise the handling of On-us transactions via the CSM.

Context

Traditionally, when both parties are with the same bank, settlement occurs internally rather than through a scheme.

In some cases, though, customers might want to send payments to themselves via a scheme. This is known as on-us-via-CSM.

Identifying On-us via CSM

By default, a payment is deemed to be on-us if the debtor’s BIC is the same as the creditor agent’s BIC. This functionality may be insufficient in cases such as:

  • The CSM service client is talking to multiple CSM service implementations

  • On-us determination is more complex (e.g. check against a list of BICs instead of just one-to-one)

  • The target CSM(s) don’t use BICs, or comparison should be done against more fields

The following implementation is defined by default in the CSM Service client library:

    @Override
    public boolean isCreditTransferOnUs(FIToFICustomerCreditTransferV08 fi2fi) {
        return Try.of(() ->
                        fi2fi.getCdtTrfTxInf().get(0).getDbtrAgt().getFinInstnId().getBICFI()
                                .equals(fi2fi.getCdtTrfTxInf().get(0).getCdtrAgt().getFinInstnId().getBICFI()))
                .getOrElse(this::failedToDetermine);
    }

    @Override
    public boolean isStatusRequestOnUs(FIToFIPaymentStatusRequestV03 fi2fi) {
        return Try.of(() -> fi2fi.getTxInf().get(0).getOrgnlTxRef().getDbtrAgt().getFinInstnId().getBICFI()
                        .equals(fi2fi.getTxInf().get(0).getOrgnlTxRef().getCdtrAgt().getFinInstnId().getBICFI()))
                .getOrElse(this::failedToDetermine);
    }

And the bean is defined as such:

    @Bean
    @ConditionalOnMissingBean
    public OnUsDeterminer onUsDeterminer() {
        return new DefaultOnUsDeterminer();
    }

If wishing to override this functionality to implement a custom on-us determination functionality instead of the default, create a new OnUsDeterminer implementation, and create a bean with the same name and signature, to use your custom implementation instead of the default.

Note that if not implementing on-us via the CSM, there is no need to disable any on-us functionality.

Detecting On-us via CSM

If the OnUsDeterminer determines that a payment is on-us via CSM, it will set a boolean in the SupportingContext called onus which can be inspected when handling any response:

    @Override
    public CompletionStage<Void> handleClearAndSettleResponse(final ReceivingContext receivingContext, final ClearAndSettleResponse response) {
        var onus = Boolean.parseBoolean(response.getCustomBusinessData().getMetaData().getValues().get(ON_US));
        if (onus) {
            // do on-us-specific stuff
        } else {
            // normal clear-and-settle response handling
        }
    }

Handling On-us via CSM inside an IPF flow

A common challenge with on-us via CSM is recognising which message is for which flow. This is because certain messages, specifically pacs.002 messages, can be used in different situations as part of a credit transfer transaction:

Sequence number Type of pacs.002 message IPF API Message Direction Purpose

1

Creditor PSR

ReceivePaymentResponse

IPF to CSM

Accept/reject a payment

2

Debtor PSR

ClearAndSettleResponse

CSM to IPF

Accept/Reject response from creditor agent

3

Creditor PSR Confirmation

ReceivePaymentSettledRequest

CSM to IPF

Final settlement notification

In many payment schemes, the pacs.002 messages in 2 and 3 will look identical, so CSM Services cannot determine which CSM message maps to which IPF API message, and may incorrectly label both as ClearAndSettleResponse. This means that the creditor leg of an on-us-via-CSM payment may remain incomplete:

onus-via-csm-bad

There are several ways to reinterpret the third pacs.002 as a ReceivePaymentSettledRequest. Below is one suggested approach:

Extra Processing!

Implementing the suggestion below introduces extra processing. To avoid performance issues with processing normal payments, be sure to only perform the below when onus is true as the extra steps below are unnecessary for normal payment processing.

When handleClearAndSettleResponse is called and onus is true, check the status of the debtor transaction (using getAggregate()):

  1. If the debtor flow is not complete, forward to the debtor flow

  2. If the debtor flow is complete:

    1. Map the ClearAndSettleResponse (Debtor PSR) to a ReceivePaymentSettledRequest (Creditor PSR Conf)

    2. Determine the creditor flow’s AssociationId (from ODS or TransactionCacheService or otherwise)

    3. Forward to the creditor flow

onus-via-scheme-opt1

The sequence above should result in both the debtor and creditor flows completing as they have all the relevant messages that they are expecting.