Callbacks

API clients can associate some resources with a callback_uri in order to enable asynchronous communication between the client and server. At certain events mCASH can trigger a callback to specified callback_uri. E.g. if the callback URI is an HTTP URI, an HTTP POST request will be made to the URI. The data sent with the callback is referred to as a "callback message" (or just "message"). The message consists of a meta part and an object part, the latter containing the actual message data, while the former is meta information about the callback. Note that you do not have to know everything about callbacks in order to implement an API client. However, all developers should read the Security considerations section.

Callbacks support several protocols (see Supported protocols) For protocols that are considered secure the callback will contain the entire message. Let us first consider an example where the callback is made using a secure protocol. The example callback_uri of the resource is https://callbackserver.test/notification/qWeR/, which is an HTTPS URI.

POST /notification/qWeR/ HTTP/1.1
HOST: callbackserver.test
Content-Type: application/vnd.mcash.api.merchant.v1+json
Authorization: RSA-SHA256 <rsa_signature>
X-Mcash-Content-Digest: SHA256=<content_sha256>

{
    "meta": {
        "id": "RzeUPFP1T5WkWd46tX8Hxg",
         "event": "test_event",
         "uri": "https://server.test/my_resource/1/"
    },
    "object": {"text": "Hello World"},
}

Notice the headers Authorization and X-Mcash-Content-Digest. The values of these headers contain the information necessary for the client to authenticate the callback from mCASH. See Verifying signatures from mCASH for a description of the signature method used in requests from mCASH.

For insecure protocols, mCASH will only send non-sensitive meta-information. In this example the callback_uri is http://callbackserver.test/notification/qWeR/ (HTTP):

POST /notification/qWeR HTTP/1.1
HOST: callbackserver.test
Content-Type: application/vnd.mcash.api.merchant.v1+json

{
    "meta": {
        "id": "RzeUPFP1T5WkWd46tX8Hxg",
        "event": "test_event",
        "uri": "https://server.test/my_resource/1/"
    }
}

Here the uri field contains a URI that points to an endpoint on an mCASH server where the object part can be retrieved using an HTTPS GET.

GET /my_resource/1/ HTTP/1.1
HOST: server.test
HTTP/1.1 200 OK
Content-Type: application/vnd.mcash.api.merchant.v1+json

{"text": "Hello World"}

Events

The value in the event field in the meta part of the message is called the message event or just event. The event says something about why the callback was made and how to interpret the object part (a data schema is defined for each event).

Payment request

Several events are associated with the different transitions in payment request state:

  • payment_authorized (User has accepted a payment request. Used for both AUTH and SALE requests)
  • payment_captured
  • payment_auth_released
  • payment_aborted_by_customer
  • payment_aborted_by_merchant
  • payment_authorization_renewed
  • payment_authorization_expired
  • payment_request_expired

As these events reflect the state of the payment request at the time the callback was made, the object part will contain the same data as what can be retrieved from the payment request outcome endpoint. The data schema is:

currency : Currency : required
  • Data required (new or existing on update)
  • length == 3
3 chars https://en.wikipedia.org/wiki/ISO_4217
amount : Money : optional : default=null
    Amount
    additional_amount : Money : optional : default=null
      Additional amount might have been changed by user if additional_edit was true
      auth_amount : Money : optional : default=null
        The authorized amount. If doing partial captures, this will show the amount still available in the authorization for subsequent captures; auth_amount = amount - sum(captured amounts)
        auth_additional_amount : Money : optional : default=null
          The authorized additional amount. If doing partial captures, this will show the part of additional amount still available in the authorization for subsequent captures; auth_additional_amount = additional_amount - sum(captured additional amounts)
          captures[] : Capture : optional : default=null
            List of captures.
            refunds[] : Refund : optional : default=null
              List of refunds.
              status : String : optional : default=null
              • Value in ok, fail, auth, pending
              Payment request status (see above)
              status_code : Integer : optional : default=null
                Payment request status code (see above).
                customer : PersonIdentifier : optional : default=null
                  Customer identifier as originally registered by POS.
                  date_modified : DateTime : optional : default=null
                    Last modified date
                    date_expires : DateTime : optional : default=null
                      Expiration date for current status. After a payment authorization is given this may extend beyond the original expiry date given in the payment request. An authorization expires after 3 days. When the payment request expires it is marked as failed (whether in pending or authorized state).
                      credit : Boolean : optional : default=false
                        Whether the received payment was a credit payment.
                        interchange_fee : Money : optional : default=null
                          Interchange fee to be deducted if credit payment.
                          transaction_fee : Money : optional : default=null
                            Transaction fee to be deducted.
                            report_id : String : optional : default=null
                              The Report that this transaction is included in.
                              report_uri : String : optional : default=null
                              • Optional
                              • URL
                              Endpoint for the report that contains the current state of the payment request.
                              ledger : String : optional : default=null
                              • Optional
                              ID of ledger this payment request is included in
                              attachment_uri : String : optional : default=null
                              • Optional
                              • URL
                              Endpoint for Attachment uploads, such as electronic receipts. This URI has a limited time to live, and a new URI is generated each time outcome is retrieved.
                              pos_id : String : required
                              • Data required (new or existing on update)
                              The POS this request originates from, used for informing user about origin
                              pos_tid : String : required
                              • Data required (new or existing on update)
                              Local transaction id for POS. This must be unique for the POS
                              tid : String : required
                              • Data required (new or existing on update)
                              mCASH transaction id
                              permissions : AccessTokenResponse : optional : default=null
                                If payment request was combined with a permission request, this field will contain the permission request outcome. Same as returned by a GET the permission request outcome endpoint

                                Permission request

                                There are two events associated with permission requests:

                                • permission_request_answered (User has processed the request and accepted or declined access to one or more resources)
                                • permission_request_expired

                                The same data is available at the outcome endpoint, with response schema:

                                access_token : String : optional : default=null
                                • Optional
                                Access token
                                id_token : String : optional : default=null
                                • Optional
                                A JWT that contains identity information about the user that is digitally signed by mCASH
                                token_type : String : required
                                • Data required (new or existing on update)
                                Type of access token, at this time it will always be Bearer
                                expires_in : Integer : optional : default=null
                                • Optional
                                Lifetime in seconds of the access token
                                refresh_token : String : optional : default=null
                                • Optional
                                Refresh token used to issue new access token after expiration
                                scope : String : optional : default=null
                                • Optional
                                • Value in address, bankid, email, fodselsnummer, openid, phone, profile, shipping_address
                                Space-delimited list of scopes. Any of: "openid" (static id, "address" (user preferred address), "profile" (name), "phone", "email", "shipping_address", "fodselsnummer"
                                currency : Currency : optional : default=null
                                • Optional
                                • length == 3
                                Currency for fee
                                transaction_fee : Money : optional : default="0.00"
                                  Permission fee to be deducted from settlement
                                  report_id : String : optional : default=null
                                    The Report that this authorization is included in
                                    report_uri : String : optional : default=null
                                    • Optional
                                    • URL
                                    Endpoint for the report that contains the state of the permission request.
                                    ledger_id : String : optional : default=null
                                    • Optional
                                    DEPRECATED, do not pass
                                    status : String : optional : default=null
                                      Permission request status
                                      status_code : Integer : optional : default=null
                                        Permission request status code
                                        pos_id : String : required
                                        • Data required (new or existing on update)
                                        The POS this request originates from, used for informing user about origin
                                        pos_tid : String : required
                                        • Data required (new or existing on update)
                                        Local transaction id for POS. This must be unique for the POS
                                        rid : String : required
                                        • Data required (new or existing on update)
                                        mCASH request id
                                        user_info : Json : optional : default=null
                                          User Info

                                          Supported protocols

                                          The part before the first colon in the callback URI determines the protocol that will be used for the callback. The meaning of the part after the colon depends on the actual protocol. The supported protocols with descriptions are given here.

                                          HTTP

                                          Example URI: http://acme.com/payment_request/Qd3/callback/

                                          mCASH will make an HTTP POST request to the specified URI. The content-type of the request will be the API media type, unless a different media type is documented for the particular callback. The request is signed by mCASH according to Authentication using RSA signature.

                                          HTTPS (secure)

                                          Example URI: https://acme.com/payment_request/Qd3/callback/

                                          Same as HTTP, except that HTTPS is considered secure which means that the object part is included in the callback message. mCASH verifies SSL certificates, so the recipient of the callback must use a CA signed certificate. If the client is going to use the data in the object part it SHOULD verify that the callback has been correctly signed by mCASH.

                                          HTTPS should be the preferred callback protocol for high-traffic clients, such as web-shops, as it is the protocol that generates least traffic between the client and mCASH.

                                          Pusher

                                          Example URI: pusher:m-acme-payment_request-Qd3

                                          Pusher uses a websocket connection that is initiated by the client. Hence, Pusher may be a convenient alternative for clients that are unable to receive HTTP(S) requests or otherwise listen for incoming connections, which is typically the case for clients that connect to the internet through a NAT. Note that Pusher should only be used by clients with relatively low traffic, such as cash registers in a store. High traffic clients, such as web-shops, should use HTTP or HTTPS.

                                          The form of a Pusher URI is pusher:<channel> where <channel> is a placeholder for the pusher channel that mCASH will send the callback message to. Merchants should prefix their channel names with m-<merchant_id>-. The event of the callback message maps to a Pusher event, so if a client for example wants to listen for a shortlink scan it has to bind to the Pusher event shortlink_scanned on the channel where it expects the shortlink scan callback.

                                          Please contact mCASH to obtain the Pusher app key to use with mCASH APIs

                                          Security considerations

                                          One important criterion for the mCASH APIs is that the responsibility for security should mostly fall on the server (mCASH) not the client. However, regarding callbacks one responsibility that falls on the client is to verify the origin of the data sent with the callback before putting it to use. There are two ways to do this.

                                          Validation of message URI

                                          If the client does not implement signature verification or is using a protocol for callbacks that does not support signatures, the callback can be verified using the following procedure:

                                          1. Verify that the hostname in the message URI in the uri field in the meta part is an mca.sh sub-domain and that the URI is HTTPS. I.e. check that the URI starts with "https:" and that the hostname ends with ".mca.sh". Example of a valid URI: https://api.mca.sh/merchant/v1/.
                                          2. Retrieve the message by making an HTTPS GET request to the message URI. Make sure that your HTTPS client library is configured to verify SSL certificates. The retrieved message can safely be used as it's origin has been verified through HTTPS.

                                          Note that some of our test environments have hostnames that are not a sub-domain of ".mca.sh", in which case this method will not work.

                                          Verify the callback signature

                                          For some protocols, like HTTP and HTTPS, it is specified that mCASH signs the callback. If the client verifies the signature according to the specified signature method, any data sent with the callback can be used safely.