> For the complete documentation index, see [llms.txt](https://docs.payments.thalescloud.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.payments.thalescloud.io/nfc-wallet-sdk-android/implement-nfc-wallet/make-payment/other-payment-methods/implement-dsrp-remote-payment.md).

# Implement DSRP remote payment

## Overview

Use Mastercard Digital Secure Remote Payment (DSRP) to generate payment data for remote acceptance, such as e-commerce.

In this flow, your **digital wallet application** generates payment data. You pass that data to your merchant system or payment gateway for authorization.

Before you start, complete **Tokenization**. See [Tokenize a card](/nfc-wallet-sdk-android/implement-nfc-wallet/tokenize-a-card.md).

{% hint style="warning" %}
The NFC Wallet SDK supports DSRP remote payment for **Mastercard** digital cards with the **MCBP 2.x profile** only.

If you need DSRP remote payment for a different profile or payment network, contact your Thales delivery team.
{% endhint %}

## SDK Integration

### Check prerequisites

Confirm the digital card supports DSRP remote payment using `DigitalizedCardDetails.paymentTypeSupported()`. This API returns a list of supported payment types. Verify that `PaymentType.DSRP` is present.

```java
public boolean isDsrpSupported(DigitalizedCardDetails card) {
    final PaymentType[] supported = card.paymentTypeSupported();

    for (PaymentType p : supported) {
        if (p == PaymentType.DSRP) {
            return true;
        }
    }
    return false;
}
```

### Create the DSRP payment input data

Create `PaymentInputData`. It contains the transaction parameters used to generate the DSRP remote payment payload.

Use `PaymentInputData.PaymentInputBuilder` with:

* `withRemotePaymentParameters` to provide `amount` and `currencyCode`
* `withMCRemotePaymentParameters` to provide `countryCode`, `transactionType`, `cryptogramDataType`, and `unpredictableNumber`

Use the following sample values as placeholders.

```java
long amount = 11900; // minor units. Example: 119.00
char currencyCode = 702; // SGD (ISO 4217 numeric)
char countryCode = 702; // Singapore (ISO 3166-1 numeric)
TransactionType transactionType = TransactionType.PURCHASE;
long unpredictableNumber = 12345;
PaymentInputData paymentInputData = new PaymentInputData.PaymentInputBuilder(PaymentType.DSRP)
                .withRemotePaymentParameters(amount, currencyCode)
                .withMCRemotePaymentParameters(countryCode, transactionType, CryptogramDataType.DE55, unpredictableNumber)
                .build();
```

`PaymentInputData` for DSRP payment has the following fields:

| Field                 | Type             | Format                                                 | Requirement | Description                                                                                       |
| --------------------- | ---------------- | ------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------- |
| `amount`              | `long`           | Numeric, minor units                                   | Required    | Set the transaction amount in minor units (no decimal separator). Example: 119.00 USD is `11900`. |
| `currencyCode`        | `char` (integer) | 3-digit ISO 4217 numeric                               | Required    | Set the transaction currency code. Example: USD is `840`.                                         |
| `countryCode`         | `char` (integer) | 3-digit ISO 3166-1 numeric                             | Required    | Set the merchant country code. Example: United States is `840`.                                   |
| `transactionType`     | Enum             | `TransactionType.PURCHASE`                             | Required    | Set the financial transaction type. For DSRP remote payments, use `TransactionType.PURCHASE`.     |
| `cryptogramDataType`  | Enum             | `CryptogramDataType.UCAF` or `CryptogramDataType.DE55` | Required    | Set the cryptogram format returned by the SDK.                                                    |
| `unpredictableNumber` | `long`           | Numeric                                                | Required    | Provide a random number generated by the merchant or payment gateway.                             |

### Generate a remote payment cryptogram

In your digital wallet application, call `PaymentBusinessService.generateApplicationCryptogram()` with `PaymentType.DSRP` to generate payment data for remote acceptance (for example, e-commerce).

You must implement a `RemotePaymentServiceListener`.

```java
final PaymentBusinessService pbs = PaymentBusinessManager.getPaymentBusinessService();
pbs.generateApplicationCryptogram(
        PaymentType.DSRP, 
        paymentInputData, 
        remotePaymentServiceListener);
```

### Implement `RemotePaymentServiceListener`

The remote payment listener handles events during DSRP cryptogram generation.

The listener has three callbacks:

* `onAuthenticationRequired`

  The SDK indicates CDCVM verification is required. See [Perform CDCVM verification](/nfc-wallet-sdk-android/implement-nfc-wallet/make-payment/implement-contactless-payments/5.-perform-cdcvm-verification.md).
* `onDataReadyForPayment`

  Remote payment output data is ready. Retrieve it using `PaymentService.getRemotePaymentData()`.

  Deactivate the payment service after you retrieve the data. If you skip deactivation, the next generation can fail with `REMOTE_PAYMENT_WRONG_STATE`.
* `onError`

  The SDK encountered a failure during remote payment generation.

  Deactivate the payment service to reset the state before retrying.

The following code snippet shows a basic implementation of the listener:

{% code expandable="true" %}

```java
public class MyRemotePaymentPaymentServiceListener implements RemotePaymentServiceListener{
    /**********************************************************/
    /*                Payment Service listener                */
    /**********************************************************/
    @Override
    public void onAuthenticationRequired(PaymentService paymentService, CHVerificationMethod chVerificationMethod, long cvmResetTimeout) {
        toggleProgress(false);
        if (chVerificationMethod == CHVerificationMethod.BIOMETRICS
                || chVerificationMethod == CHVerificationMethod.DEVICE_KEYGUARD) {
            Intent intent = new Intent(this, DeviceCVMActivity.class);
            intent.putExtra(DeviceCVMActivity.EXTRA_CVM, chVerificationMethod);
            overridePendingTransition(0, 0);
            startActivityForResult(intent, REQ_CODE_FINGERPRINT);
        } else {
            // NOTE: Not supported any other verification
            AppLogger.e(TAG, "Verification method " + chVerificationMethod + " not currently supported!");
            deactivatePaymentService();
        }
    }

    @Override
    public void onDataReadyForPayment(PaymentService paymentService, TransactionContext transactionContext) {
        toggleProgress(false);
        RemotePaymentOutputData remotePaymentData = paymentService.getRemotePaymentData();
        Toast.makeText(this, " DSRP payment data is " +remotePaymentData.getCryptogramData(), Toast.LENGTH_LONG).show();
        deactivatePaymentService();
    }

    @Override
    public void onError(SDKError<PaymentServiceErrorCode> sdkPaymentServiceErrorCode) {
        AppLogger.e(TAG, "Failed to generate DSRP payment data with error code " + sdkPaymentServiceErrorCode.getErrorCode());
        Toast.makeText(this, "Failed to generate DSRP payment data with error code " + sdkPaymentServiceErrorCode.getErrorCode(), Toast.LENGTH_SHORT).show();
        deactivatePaymentService();
    }
}
```

{% endcode %}

Pass your listener instance when you call `generateApplicationCryptogram(...)`.

### Get DSRP payment data

Get `RemotePaymentOutputData` when `RemotePaymentServiceListener.onDataReadyForPayment()` is triggered.

`RemotePaymentOutputData` contains the following fields.

| Field                  | Description                                                                                                       |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `cryptogramData`       | Byte array containing the formatted response. This is either UCAF or TLV data for the merchant to populate DE-55. |
| `dpan`                 | DPAN with any `F` padding removed (if present).                                                                   |
| `dpanSequenceNumber`   | DPAN sequence number (PSN) of the card used.                                                                      |
| `track2EquivalentData` | Track 2 equivalent data, according to ISO/IEC 7813, excluding start sentinel, end sentinel, and LRC.              |
| `PAR`                  | Payment account reference (PAR), if provided by the payment network.                                              |
| `dPanexpirationDate`   | DPAN expiration date.                                                                                             |
| `cryptogramDataType`   | Cryptogram format returned (`UCAF` or `DE55`).                                                                    |

`track2EquivalentData` includes:

* Primary Account Number
* Field separator (hex `D`)
* Expiration date (`YYMM`)
* Service code
* Discretionary data (defined by the payment network)
* Optional padding with hex `F` to align to a whole byte

### Handle errors

When `RemotePaymentServiceListener.onError(...)` is triggered, the SDK provides a `PaymentServiceErrorCode`.

Always call `PaymentBusinessService.deactivate()` in `onError(...)` to reset the payment service state before you retry.

`PaymentBusinessService.generateApplicationCryptogram(...)` throws `IllegalArgumentException` if `paymentInputData` is `null` or if the listener is `null`.

| Payment service error code       | Description                                                                       | Recommended action                                                                                                         |
| -------------------------------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| REMOTE\_PAYMENT\_WRONG\_STATE    | The payment service is already activated when trying to perform a remote payment. | Call `PaymentBusinessService.deactivate()` after each generation. Call it when the end user cancels CDCVM.                 |
| REMOTE\_PAYMENT\_OUTPUT\_INVALID | Output data cannot be parsed and is not available.                                | Retry the transaction.                                                                                                     |
| REMOTE\_PAYMENT\_NOT\_SUPPORTED  | The default card does not support remote payment.                                 | Check `DigitalizedCardDetails.paymentTypeSupported()` before payment. Use a digital card that supports `PaymentType.DSRP`. |
| REMOTE\_PAYMENT\_INPUT\_INVALID  | The input data exists but some fields are not valid.                              | Rebuild `PaymentInputData` with valid values. Ensure all required fields are set.                                          |
| NO\_DEFAULT\_CARD                | There is no default card.                                                         | Set a default card before generating a cryptogram.                                                                         |
| CARD\_OUT\_OF\_PAYMENT\_KEYS     | No payment credentials are available.                                             | Replenish payment credentials before retrying.                                                                             |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.payments.thalescloud.io/nfc-wallet-sdk-android/implement-nfc-wallet/make-payment/other-payment-methods/implement-dsrp-remote-payment.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
