# Handling Customer Notifications

Source: https://docs.gocardless.com/docs/tutorials/handling-customer-notifications

# Handling Customer Notifications

GoCardless automatically sends notifications to customers whenever an event happens in our system. For example, when a payment has been created, the customer will receive an email that informs them about the amount, description and cause of the payment.

You have the ability to send some of these notifications yourself, and we'll honour your request if it is made within our stated deadline: otherwise, we will send the notification ourselves.

**This feature is especially handy if you want to combine multiple notifications into a single one, for example:**

- a welcome email which includes mandate setup information
- an email that lists the schedule of all upcoming payments
- an email that combines a notice of a new mandate and a new subscription

**Here is an example of the workflow:**

1. Your integration creates a payment
2. The payment event schedules a `payment_created `notification
3. We send a webhook to your application which includes notification metadata
4. Your application notifies us that it will handle the notification

**There are three conditions that you must satisfy to be able to handle a notification:**

1. You must be approved to handle notifications of this type
2. You must be the "notification owner" for that payment, mandate, or subscription
3. You must be on the Pro package

> **Info: For Partners**
> Note that your merchants do not need to be on the Pro package to use this feature.

**Currently, the following notifications can be handled:**

- `payment_created`
- `mandate_created`
- `subscription_created`

### Getting approved to handle notifications

To be able to handle customer notifications yourself, you will need to be granted permission. Please get in touch with the [GoCardless support team](mailto:help@gocardless.com) to get started.

> **Info:**
> Our recommended workflow involves getting permissions in the sandbox environment, which will allow
>   you to test handling notifications. Once you've got compliant templates for those notifications,
>   you'll need to submit them for approval, after which GoCardless will then enable this feature in
>   the live environment.

Permissions are very granular and cover the type & scheme of the notification. For example, you might be approved to handle the `payment_created` notification just in the scheme `sepa`.

Compliant notifications must include all of the required information for that notification type, and be sent within the correct interval. More information about the required information for each type of notification can be found [in our platform guides](https://gocardless.com/direct-debit/notifications/).

### Notification ownership

A merchant may be connected to multiple partners, or have multiple integrations, so to avoid the problem of multiple integrations all trying to handle the same notification, we track the "owner" for all customer notifications in our system.

Only the owner will have the ability to handle notifications for that resource, falling back to GoCardless if the notification deadline is missed.

The owner is usually defined as the creator of that resource. For example, if your integration creates a payment, the owner will be your integration. Currently, our system does not permit any kind of ownership transfer from one integration to another. Resources created via dashboard will not record any owner (and therefore cannot be handled by your integration).

### Getting notified about notifications

Notification information is currently only delivered in webhooks. When your application receives a webhook, each event may include a `customer_notifications` payload, which contains a list of one or more notifications that were triggered by that event. (If you don't receive this information, it's because you are not the owner for that resource or have not been granted any permissions):

```http
POST https://example.com/webhooks HTTP/1.1
Content-Type: application/json
,
      "details": ,
      "customer_notifications": [
        
      ]
    }
  ]
}
```

Note that each notification for an event includes an `id`, `type`, `deadline` and `mandatory` flag:

- `id `is used to handle the notification (see below)
- `type `can be used to filter notifications that you don't handle. For example, if your integration only handles `payment_created `notifications, you can safely ignore notifications that are of another type.
- `deadline `is the time by which your application must respond. If we don't hear from you before this deadline, we'll send the notification ourselves. The deadline is typically 10 minutes from the point at which we send the webhook but in the case of `payment_created `notifications, the deadline is the last possible time to notify the customer before the payment collects (this mirrors GoCardless' behaviour).
- `mandatory `is whether the notification needs to be handled by somebody (currently always true).

### Handling notifications yourself

If your application intends to handle a notification, you should let us know before you take action. If you wait until **after** sending the notification, there is a chance that we also sent it in the meantime (e.g. if the deadline had elapsed), which would result in the customer receiving two notifications, one from each of us.

> **Info:**
> If you had already sent the notification(s) previously (e.g. a welcome email which included
>   mandate setup information, or an email that listed upcoming payments including this one), you'll
>   still need to tell us that you have handled each notification.

So, we recommend that you declare your intent first, and then send the notification using whichever mechanism is most appropriate for your system:

```php
<?php
// We recommend storing your webhook endpoint secret in an environment variable
// for security
$webhook_endpoint_secret = getenv("GOCARDLESS_WEBHOOK_ENDPOINT_SECRET");
$access_token = getenv("GOCARDLESS_ACCESS_TOKEN");
$request_body = file_get_contents('php://input');

$headers = getallheaders();
$signature_header = $headers["Webhook-Signature"];

try  elseif ($notification->type === "payment_created") 
        }
    }

    header("HTTP/1.1 204 No Content");

} catch(\\GoCardlessPro\\Core\\Exception\\InvalidSignatureException $e) 
```

```python
# Here, we're using a Django view, but essentially the same code will work in

# other Python web frameworks (e.g. Flask) with minimal changes

from django.views.generic import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from django.http import HttpResponse

from gocardless_pro import webhooks, Client
from gocardless_pro.errors import InvalidSignatureError

from my_services import my_notification_system

# Handle the incoming Webhook and check its signature.

class Webhook(View):
@method_decorator(csrf_exempt)
def dispatch(self, *args, \*\*kwargs):
return super(Webhook, self).dispatch(*args, \*\*kwargs)

    def get_events(self, request):
        # We recommend storing your webhook endpoint secret in an environment
        # variable for security
        secret = os.environ['GC_WEBHOOK_SECRET']
        signature = request.META["HTTP_WEBHOOK_SIGNATURE"]
        body = request.body.strip()

        # The parse method will first verify the signature of the webhook body
        # in order to ensure it has not been tampered with. Without a valid
        # signature, a gocardless_pro.errors.InvalidSignatureError will be
        # thrown.
        return webhooks.parse(body, secret, signature)

    def post(self, request, *args, **kwargs):
        client = Client(access_token=os.environ['GC_TOKEN'], environment='live')

        try:
            # We might want to handle mandate_created emails and send an email
            # which includes both the mandate and upcoming payments for it.
            for event in self.get_events(request):
                for notification in event.customer_notifications:
                    if notification.type == "mandate_created":
                        client.customer_notifications.handle(notification.id)
                        # We recommend processing data asynchronously, so as to
                        # promptly respond to the webhook and avoid timeouts. In
                        # this example, the application uses a message queue to
                        # send the email.
                        my_notification_system.enqueue_email(notification, event)
                    elif notification.type == "payment_created":
                        # If your mandate_created email properly notifies of the
                        # payment schedule, we still need to handle the
                        # payment_created notification to prevent GoCardless
                        # from sending it.
                        client.customer_notifications.handle(notification.id)

            return HttpResponse(200)
        except InvalidSignatureError:
            return HttpResponse(498)
```

```ruby
require "gocardless_pro"

client = GoCardlessPro::Client.new(
access_token: ENV["GC_ACCESS_TOKEN"],
environment: :sandbox,
)

args = 

# The parse method will first verify the signature of the webhook body

# in order to ensure it has not been tampered with. Without a valid

# signature, a GocardlessPro::Webhook::InvalidSignatureError will be

# thrown.

begin
GoCardlessPro::Webhook.parse(\*\*args).each do |event|
notifications = event.customer_notifications

    # We might want to handle mandate_created emails and send an email which
    # includes both the mandate and upcoming payments for it.
    mandate_notifications = notifications.select 

    mandate_notifications.each do |notification|
      client.customer_notifications.handle(notification.id)
      # We recommend processing data asynchronously, so as to promptly respond to
      # the webhook and avoid timeouts. In this example, the application uses a
      # message queue to send the email.
      MyNotificationSystem.enqueue_email(notification, event)
    end

    # If your mandate_created email properly notifies of the payment schedule, we
    # still need to handle the payment_created notification to prevent GoCardless
    # from sending it.
    payment_notifications = notifications.select 

    payment_notifications.each do |notification|
      client.customer_notifications.handle(notification.id)
    end

end

head 204
rescue GocardlessPro::Webhook::InvalidSignatureError
head 498
end
```

```java
package com.myInvoicingApp;

// Use the POM file at
// https://raw.githubusercontent.com/gocardless/gocardless-pro-java-maven-example/master/pom.xml

@RestController
public class WebhookHandler  else if (n.getType() == Type.PAYMENT_CREATED) 
                }
            }

            return new ResponseEntity("", HttpStatus.NoContent);
        } catch(InvalidSignatureException e) 
    }

    private void sendNotification(CustomerNotification notification, Event event) 

}
```

```javascript
const process = require("process");
const http = require("http");

const webhooks = require("gocardless-nodejs/webhooks");

const webhookEndpointSecret = process.env.WEBHOOK_ENDPOINT_SECRET;

const server = http.createServer(function (request, response) 

let data = "";
request.on("data", (chunk) => );
request.on("end", () =>  catch (e) 

});
});

const port = 3000;
const host = "127.0.0.1";
server.listen(port, host);
console.log(\`Listening at http://\$:\$\`);
```

```c#
[HttpPost]
public ActionResult HandleWebhook()

                if (notification.Type == "payment_created")
                
            }
        }

        return new HttpStatusCodeResult(HttpStatusCode.OK);
    }
    catch (InvalidSignatureException e)
    

}
```

```http
POST https://api.gocardless.com/customer_notifications/EV1D18JEXAMPLE/actions/handle HTTP/1.1

HTTP/1.1 201 Created

}
}
```

```go
package main

	"context"
	"fmt"
	"http"

    gocardless "github.com/gocardless/gocardless-pro-go/v6"

)

type PendingNotification struct 

func main() 
client, err := gocardless.New(config)
if err != nil 

    sendNotification := func(n gocardless.CustomerNotification, event gocardless.Event) 
    	messageQueue.Enqueue(pendingNotification)
    }

    parseEvent := func(event gocardless.Event) 
    			client.CustomerNotifications.Handle(ctx, n.Id, customerNotificationHandleParams)
    		}
    	}
    }

    http.HandleFunc("/webhookEndpoint", func(w http.ResponseWriter, r *http.Request) ))
    	wh.ServeHTTP(w, r)
    })

}
```

Alternatively, if your application does not respond, or does not respond before the deadline, GoCardless will send the notification instead and there will be no opportunity to handle after that point.

In all cases, GoCardless will record the outcome for each notification for audit purposes.

> **Info:**
> If you are taking payments in Denmark, please note that Danish banks typically provide a monthly
>   summary of requested payments to their customers. For this reason, **GoCardless does not send
>   `payment_created` notifications to Danish payers**, to avoid double-notifying them. If you wish to
>   send a payment-related notification, you can of course do so, but bear in mind that it will not be
>   the only one received by the payer.

## What's next?