> 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/click-to-pay/integrate-the-d1-sdk/getting-started/configuration/4.-push-notifications/message-handling.md).

# Message handling

{% hint style="info" %}
This section is only applicable for NFC Wallet.
{% endhint %}

### Process a push notification

When receiving a push notification, the issuer application shall provide the notification to D1 SDK using `D1Task.processNotification()`.

<figure><img src="/spaces/62lLFDcmLCeqqwmy4Fee/files/9iDBIxqikD7PS89v8SZl" alt=""><figcaption><p>Push notification processing flow</p></figcaption></figure>

### Message types and payloads

The SDK processes the push message, returns data contains `PushResponseKey.MESSAGE_TYPE`, `PushResponseKey.CARD_ID` or `PushResponseKey.LAST_CALL_TIMESTAMP`. The following table shows the possible message type and corresponding payloads:

| Message Type                                                                                | Card ID | Last Call Timestamp | Comments                                                                                                                                                               |
| ------------------------------------------------------------------------------------------- | ------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| PushResponseKey.TYPE\_CARD\_STATE                                                           | Yes     | No                  |                                                                                                                                                                        |
| PushResponseKey.TYPE\_REPLENISHMENT                                                         | Yes     | No                  |                                                                                                                                                                        |
| PushResponseKey.TYPE\_TRANSACTION\_NOTIFICATION                                             | Yes     | Yes                 |                                                                                                                                                                        |
| PushResponseKey.TYPE\_AUTHN                                                                 | No      | No                  |                                                                                                                                                                        |
| PushResponseKey.TYPE\_CARD\_RENEWAL                                                         | No      | No                  | Message received after a successful card renewal. To reflect the new card ID, a resynchronisation of the card ID is required. For more details, refer to Card Renewal. |
| PushResponseKey.TYPE\_MESSAGING (iOS) PushResponseKey.TYPE\_MESSAGE\_NOTIFICATION (Android) | Yes     | No                  |                                                                                                                                                                        |
| PushResponseKey.TYPE\_UNKNOWN                                                               | No      | No                  | Message for the application.                                                                                                                                           |

### Examples

{% tabs %}
{% tab title="Android (FCM)" %}
{% code overflow="wrap" %}

```java
public class D1PayFirebaseService extends FirebaseMessagingService {
    private D1Task d1Task = null;

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        if (d1Task == null) {
            d1Task = new D1Task.Builder()
                    .setContext(getApplicationContext())
                    .build();
        }

        // if 3DS feature is enabled, create d1Authn instance before proccessing the pushNotification with the same d1Task instance that is used to 'processNotification'
        // it is required to display prompt with an activity if it is a push that requests for d1Authn authentication
        // Application interaction is required during the processing to display promts to end user.
        D1Authn d1Authn = d1Task.getD1Authn(activity, new AuthnCallback(){
           
            @Override
            public void onTransactionDataConfirmation(@NunNull Map<String, String> map, @NonNull AuthnUserConfirmationCallback authnUserConfirmationCallback){
              // The 'map' contains the transaction data that is to be authenticated. 
              // Application to display the content, prompt end uer either to 'proceed' or to 'deny' the authentication request.
              
              // To proceed: when uer selects proceed
              // once proceed, UI will be prompted for authentication based on the selected AuthnType enrolled.
              authnUserConfirmationCallback.proceed();

              // To cancel: when user selects cancel
              authnUserConfirmationCallback.cancel();
            }

            @Override
            public onBiometricPromptMessage(){
              // Provide a message prompt for the authentication prompt. Application can customize the value.
              return "Message to be displayed to the user during biometric prompt";
            }
        
        });
        

        d1Task.processNotification(remoteMessage.getData(), new D1Task.Callback<String>() {
            @Override
            public void onSuccess(@Nullable String d1CardID) {
                // Proceed with subsequent flows
            }

            @Override
            public void onError(@NonNull D1Exception exception) {
                // Refer to D1 SDK Integration – Error Management section
            }
        });

        // Other application logic ...
    }

    // ...
}
```

{% endcode %}
{% endtab %}

{% tab title="iOS (APNs)" %}
{% code overflow="wrap" %}

```swift
extension AppDelegate {
    func application(
        _ application: UIApplication,
        didReceiveRemoteNotification userInfo: [AnyHashable : Any],
        fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
    ) {
        if let userInfo = userInfo as? [String: Any] {
            d1Task.processNotification(userInfo) { response, error in
                guard error == nil else {
                    // Refer to D1 SDK Integration – Error Management section.
                    completionHandler(.noData)
                    return
                }
                
                guard let response = response, let type = response[PushResponse.Key.messageType] else {
                    completionHandler(.noData)
                    return
                }

                guard type != PushResponse.typeUnknown else {
                    // The notification is not recognized by the SDK.
                    completionHandler(.noData)
                    return
                }

                guard type == PushResponse.typeMessaging,
                      let id = response[PushResponse.Key.messageID],
                      let message = Message.message(withID: id) else {
                    completionHandler(.noData)
                    return
                }

                let content = UNMutableNotificationContent()
                // Constructs the notification based on message
                content.title = message.title ?? "Notification"
                content.body = message.message ?? ""
                content.targetContentIdentifier = message.action.

                // Shows the notification to the end user.
                let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
                let request  = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
                UNUserNotificationCenter.current().add(request) { error in }
                completionHandler(.newData)
            }
        } else {
            completionHandler(.noData)
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
For Android, apps targeting API level 33 must handle runtime notification permission. For details, see [Notification runtime permission](https://developer.android.com/develop/ui/views/notifications/notification-permission).
{% endhint %}

### Notification filtering

Internally, D1 SDK processes the notification with the following key value pairs. The application may filter based on these values and only pass such notifications to the SDK.

| Key      | Value             |
| -------- | ----------------- |
| `sender` | `CPS`             |
| `sender` | `MG`              |
| `sender` | `TNS`             |
| `topic`  | `D1_NOTIFICATION` |


---

# 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/click-to-pay/integrate-the-d1-sdk/getting-started/configuration/4.-push-notifications/message-handling.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.
