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 callbacks_security 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.

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.