Skip to content

Webhook notifications

A webhook notification is a way to call a script on one of your own web servers whenever a transaction or a subscription is processed.


Set up webhook requests

To receive a webhook request from the PayCross system, pass notification_url in transaction request parameters.

{
    ....

    "notification_url":"https://your-domain.com/notification",

    ....
}

Webhook request use HTTP Basic authentication with Shop ID and Secret Key.


Verify webhook requests

A webhook request contains the same parameters as a transaction or a subscription response.

The Content-Signature header contains the RSA digital signature of the request, that is generated with the shop RSA private key known only to the PayCross.

If you need to verify the notifications, check the digital signature of the request on your side with your RSA public key and compare it with the one received in the request. If the signatures coincide, it confirms the authenticity and integrity of the notification.

Info

When verifying the signature, make sure that:

  • The hash is calculated by the SHA256 function;
  • A public key is a key obtained in your PayCross back office;
  • The calculated value is transmitted in Base64 encoding.

Info

When using payment widget integration option with public key, when verifying the webhook notification, pay special attention to the following parameters:

  • amount,
  • currency,
  • test,
  • tracking_id
Example of the PHP code to verify the digital signature
# shop_public_key - shop public key
# signature - Content-Signature header value
# rawBody - request body

$public_key = str_replace(array("\r\n", "\n"), '', $shop_public_key);
$public_key = chunk_split($public_key, 64);
$public_key = "-----BEGIN PUBLIC KEY-----\n$public_key-----END PUBLIC KEY-----";

$signature = base64_decode($signature);

$key = openssl_pkey_get_public($public_key);

$a = openssl_verify($rawBody, $signature, $key, OPENSSL_ALGO_SHA256);

var_dump($a);
Example of the Ruby code to verify the digital signature
require 'openssl'
require 'base64'

shop_public_key = "" # Shop public key 
signature = "" # Content-Signature header value
request_raw_body = "" # Request body

public_key = OpenSSL::PKey::RSA.new(Base64.decode64(shop_public_key))

if public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(signature), request_raw_body)
  true
else
  false
end    

Processing webhook notifications

Your web server should return 200 HTTP status code if a webhook notification is processed successfully. Otherwise, PayCross will re-post webhook data later.

Example of the webhook request for a payment transaction
{
  "transaction": {
    "uid": "dd6ee60c-d30a-4348-b84c-86a4ef1a137d",
    "status": "successful",
    "amount": 100,
    "currency": "EUR",
    "description": "Test transaction ütf",
    "type": "payment",
    "payment_method_type": "credit_card",
    "tracking_id": "tracking_id_000",
    "message": "Successfully processed",
    "test": true,
    "created_at": "2023-04-14T13:07:01.836Z",
    "updated_at": "2023-04-14T13:07:05.530Z",
    "paid_at": "2023-04-14T13:07:05.495Z",
    "expired_at": null,
    "recurring_type": null,
    "closed_at": null,
    "settled_at": null,
    "manually_corrected_at": null,
    "language": "en",
    "credit_card": {
      "holder": "John Doe",
      "stamp": "d9a78f040a8427c65da2c5569e6411c3641a5537fcfd2d2bf9f866abf3611c7d",
      "brand": "visa",
      "last_4": "1006",
      "first_1": "4",
      "bin": "401200",
      "issuer_country": null,
      "issuer_name": null,
      "product": null,
      "exp_month": 10,
      "exp_year": 2026,
      "token_provider": null,
      "token": null
    },
    "receipt_url": "https://admin.pay-cross.com/customer/transactions/dd6ee60c-d30a-4348-b84c-86a4ef1a137d/42fe9b2e3ed56e98b426e946882cd10d71cd8ee0593373b00196413e28338dd7?language=en",
    "status_code": null,
    "gateway": {
      "iframe": true
    },
    "id": "dd6ee60c-d30a-4348-b84c-86a4ef1a137d",
    "additional_data": {
      "browser": {
        "screen_width": 1920,
        "screen_height": 1080,
        "screen_color_depth": 24,
        "language": "en",
        "java_enabled": false,
        "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
        "time_zone": -180,
        "time_zone_name": "Europe",
        "accept_header": "json",
        "window_height": 667,
        "window_width": 600
      }
    },
    "redirect_url": "https://gateway.pay-cross.com/process/dd6ee60c-d30a-4348-b84c-86a4ef1a137d",
    "payment": {
      "auth_code": "654321",
      "bank_code": "05",
      "rrn": "999",
      "ref_id": "777888",
      "message": "Payment was approved",
      "amount": 100,
      "currency": "EUR",
      "billing_descriptor": "test descriptor",
      "gateway_id": 645,
      "status": "successful"
    },
    "customer": {
      "ip": "127.0.0.1",
      "email": "[email protected]",
      "device_id": "12312312321fff67",
      "birth_date": "1980-01-31"
    },
    "billing_address": {
      "first_name": "John 1",
      "last_name": "Doe",
      "address": "1st Street",
      "country": "US",
      "city": "Denver",
      "zip": "96002",
      "state": "CO",
      "phone": "4567898765467"
    }
  }
}
Example of the webhook request body for a trial subscription
{
  "id": "sbs_962f994ca74420d3",
  "state": "trial",
  "tracking_id": null,
  "device_id": null,
  "created_at": "2023-04-13T06:39:36.593Z",
  "renew_at": "2023-05-13T06:41:26.581Z",
  "active_to": "2023-05-13T06:41:26.581Z",
  "card": {
    "holder": "JOHN DOE",
    "stamp": null,
    "brand": "visa",
    "last_4": "1006",
    "first_1": "4",
    "bin": null,
    "issuer_country": null,
    "issuer_name": null,
    "product": null,
    "token": "606760b7-74da-44fb-a730-13a9ee28d620",
    "token_provider": null,
    "exp_month": 12,
    "exp_year": 2026,
    "sub_brand": null
  },
  "customer": {
    "id": "cst_4a708bf13a483278"
  },
  "paid_billing_cycles": 1,
  "number_failed_payment_attempts": 0,
  "additional_data": {},
  "plan": {
    "id": "pln_7f2e3edfbca72afc",
    "title": "Test plan",
    "name": "Test plan",
    "description": "Subscription. Main period: €9.99 each 1 month. Trial: €4.99 each 1 month.",
    "amount": 499,
    "currency": "EUR",
    "language": "en",
    "infinite": true,
    "billing_cycles": null,
    "created_at": "2023-04-13T06:38:58.604Z",
    "updated_at": "2023-04-13T06:38:58.604Z",
    "trial": {
      "amount": 499,
      "interval": 1,
      "interval_unit": "month"
    },
    "plan": {
      "amount": 999,
      "interval": 1,
      "interval_unit": "month",
      "visible_fields": [
        "last_name",
        "first_name",
        "email"
      ]
    },
    "number_payment_attempts": 3,
    "prevent_payments_at_night": true,
    "test": true,
    "pay_url": "https://data.pay-cross.com/plans/pln_7f2e3edfbca72afc/pay",
    "payment_url": "https://data.pay-cross.com/plans/pln_7f2e3edfbca72afc/pay",
    "confirm_url": "https://panel.pay-cross.com/v2/confirm_order/pln_7f2e3edfbca72afc/160"
  },
  "last_transaction": {
    "uid": "971c8eb0-f4db-4a04-ba64-840e3427656e",
    "status": "successful",
    "message": "Successfully processed",
    "created_at": "2023-04-13T06:41:22.913Z"
  },
  "event": "created.subscription"
}
Example of the webhook request for an active or renewed subscription
{
  "card": {
    "token": "2ed0b389f63c9198160bd7b8e98f6b42eb4c56e3b659a8070248b28cd3376d9d",
    "holder": "John Doe",
    "stamp": "b3839d334ba40e89168d60cd9f9d1390aee3fe67dd4d5c41adbf3998043eaef8",
    "brand": "visa",
    "last_4": "0000",
    "first_1": "4",
    "bin": "420000",
    "issuer_country": null,
    "issuer_name": null,
    "product": null,
    "token_provider": null,
    "exp_month": 1,
    "exp_year": 2026
  },
  "created_at": "2015-06-18T12:02:42.521Z",
  "customer": {
    "id": "cst_ae00d2582d001228"
  },
  "device_id": "any device_id",
  "id": "sbs_f140af88af4aaf88",
  "last_transaction": {
    "created_at": "2015-01-12T09:04:59.000Z",
    "message": "Successfully processed",
    "status": "successful",
    "uid": "4107-310b0da80b"
  },
  "plan": {
    "currency": "USD",
    "id": "pln_05e0756ed24eec5c",
    "plan": {
      "amount": 20,
      "interval": 7,
      "interval_unit": "day"
    },
    "title": "Title 1",
    "trial": {
      "amount": 10,
      "interval": 40,
      "interval_unit": "hour"
    }
  },
  "renew_at": "2015-06-24T12:02:42.499Z",
  "state": "active",
  "tracking_id": "any tracking_id"
}
Example of the webhook request for a canceled subscription
{
  "card": {
    "token": "9990edb8e6f2af5d93a6259b690c50a7410bf9f97235f2e051345e01b580f699",
    "holder": "John Doe",
    "stamp": "b3839d334ba40e89168d60cd9f9d1390aee3fe67dd4d5c41adbf3998043eaef8",
    "brand": "visa",
    "last_4": "0000",
    "first_1": "4",
    "bin": "420000",
    "issuer_country": null,
    "issuer_name": null,
    "product": null,
    "token_provider": null,
    "exp_month": 1,
    "exp_year": 2026
  },
  "created_at": "2015-06-18T12:02:42.731Z",
  "customer": {
    "id": "cst_2a46e8b7ff87df2d"
  },
  "device_id": "any device_id",
  "id": "sbs_1cc338f74bc9bfb7",
  "last_transaction": null,
  "plan": {
    "currency": "USD",
    "id": "pln_0b4ba2f1ab0c1988",
    "plan": {
      "amount": 20,
      "interval": 7,
      "interval_unit": "day"
    },
    "title": "Title 1",
    "trial": {
      "amount": 10,
      "interval": 40,
      "interval_unit": "hour"
    }
  },
  "renew_at": null,
  "state": "canceled",
  "tracking_id": "any tracking_id"
}
Example of the webhook request for an expired payment token

If a payment token wasn't paid in time, the notification is sent at expired_at date or in 24 hours after the token was created, if the expired_at date wasn't defined.

{
  "token":"311300d08dc7f22ae37272fac6513921d4c99ca24dcaccf4392a2606fe8f1877",
  "shop_id":1,
  "transaction_type":"payment",
  "gateway_response":null,
  "order":{
    "currency":"USD",
    "amount":4299,
    "description":"Order description",
    "tracking_id":null,
    "additional_data":{

    },
    "expired_at":"2017-06-01T13:01:06.123Z"
  },
  "settings":{
    "success_url":"http://127.0.0.1:4567/success",
    "fail_url":"http://127.0.0.1:4567/fail",
    "decline_url":"http://127.0.0.1:4567/decline",
    "notification_url":"http://your_shop.com/notification",
    "cancel_url":"http://127.0.0.1:4567/cancel",
    "language":"en",
    "customer_fields":{
      "hidden":[
        "phone",
        "address"
      ],
      "read_only":[
        "email"
      ]
    }
  },
  "customer":{
    "first_name":null,
    "last_name":null,
    "address":null,
    "city":null,
    "country":null,
    "state":null,
    "phone":null,
    "zip":null,
    "email":"[email protected]"
  },
  "finished":false,
  "expired":true,
  "shop":{
    "name":"Shop",
    "url":"http://127.0.0.1:3009",
    "contact_email":"[email protected]",
    "contact_phone":"123456789",
    "brands":[
      "visa",
      "master",
      "maestro"          
    ]
  },
  "test":false,
  "status":"error",
  "message":"Token is expired.",
  "payment_method":{
    "id":9,
    "checkout_data_id":9,
    "types":[],
    "data":{ },
    "created_at":"2017-06-01T13:00:14.506Z",
    "updated_at":"2017-06-01T13:00:14.506Z"
  }
}