Перейти до змісту

Callbacks

Callbacks дозволяють отримувати сповіщення, коли змінюється статус операції.

Щоб налаштувати Callbacks для операцій, необхідно задати адресу callback_url у налаштуваннях інтеграції або відправляти цей параметр у запиті.

Note

Callback – асинхронна функція, тому не рекомендується для завдань із жорстким обмеженням часу. Існує ймовірність, що ваша програма отримає повідомлення не в порядку надсилання або вони продублюються. Тому на додаток до Callbacks ми рекомендуємо використовувати реконсиляцію (звірку) за API для оновлення даних у системі.

Налаштування

Для налаштування Callbacks потрібно перейти до налаштувань акаунту та додати значення «Callback URL».

Формат повідомлення

HTTP запит, який ми відправимо на ваш callback_url, матиме наступні характеристики:

  • це буде POST запит;
  • Тіло запиту буде передано в JSON API форматі;
  • об'єкти type та id обов'язково будуть у тілі запиту (а не в URL-параметрі).
{
    "data": {
        "type": "payment-invoices",
        "id": "cpi_yv1RgJ2l8ty2AxIs",
        "attributes": {
        "serial_number": "yv1RgJ2l8ty2AxIs",
        "status": "processed",
        "resolution": "ok",
        "moderation_required": false,
        "amount": 22,
        "payment_amount": 22,
        "currency": "USD",
        "service_currency": "USD",
        "reference_id": "da1b0b9d-c249-4f6e-9949-2a2f2d4b1758",
        "test_mode": true,
        "fee": 0,
        "deposit": 22,
        "processed": 1592232071,
        "processed_amount": 22,
        "refunded_amount": null,
        "processed_fee": 0,
        "processed_deposit": 22,
        "metadata": {
            "merchant_url": "https://yu.test.this"
        },
        "flow_data": {
            "action": "https://example.domain/hpp/cgi_Q0fYDFaHlqb5MCdl",
            "method": "GET",
            "params": [],
            "metadata": {
            "sid": "cgi_Q0fYDFaHlqb5MCdl",
            "token": "eyJ0eXAiOiJKV1QiLRiGCg2O...nGE7E"
            }
        },
        "flow": "hpp",
        "payment_flow": "charge",
        "created": 1592232050,
        "updated": 1592232071,
        "payload": {
            "token": null,
            "client_ip": "54.36.117.30",
            "payment_card": {
            "last": "0000",
            "mask": "512381******0000",
            "brand": "mastercard",
            "перший": "512381",
            "holder": null,
            "expiry_year": "33",
            "issuer_name": "FIRST DATA CORPORATION",
            "expiry_month": "11",
            "issuer_country": "US"
            }
        },
        "description": null,
        "descriptor": null,
        "callback_url": "https://test.doc.home",
        "return_url": "https://example.com",
        "return_urls": {
            "fail": "https://example.com/sorry-page",
            "pending": "https://example.com/wait-for-it-page",
            "success": "https://example.com/thank-you-page"
        },
        "original_data": null,
        "rrn": null,
        "approval_code": null,
        "reserved_amount": null,
        "reserve_expires": null,
        "unreserved": null,
        "source": null,
        "callback_logs": []
        },
        "relationships": {
        "payment-service": {
            "data": {
            "type": "payment-services",
            "id": "payment_card_usd_hpp"
            }
        },
        "payment-method": {
            "data": {
            "type": "payment-methods",
            "id": "payment_card"
            }
        },
        "customer": {
            "data": null
          }
        },
        "links": {
        "self": "/api/payment-invoices/cpi_yv1RgJ2l8ty2AxIs"
        }
    }
}
{
"data": {
    "type": "payout-invoices",
    "id": "cpoi_sIzOuMKJg98J22NC",
    "attributes": {
    "serial_number": "sIzOuMKJg98J22NC",
    "status": "processed",
    "resolution": "ok",
    "amount": 100,
    "payout_amount": 100,
    "currency": "USD",
    "service_currency": "USD",
    "service_amount": 100,
    "service_payout_amount": 100,
    "reference_id": "45284707-d243-439e-8b41-d657322e693b",
    "test_mode": true,
    "description": null,
    "fee": 0,
    "writeoff": 100,
    "exchange_rate": 1,
    "processed": 1621335982,
    "processed_amount": 100,
    "processed_fee": 0,
    "processed_writeoff": 100,
    "metadata": [],
    "created": 1621335974,
    "updated": 1621335982,
    "fields": {
        "card_number": "512381******0000"
    },
    "callback_url": "https://test.doc.home",
    "source": "merchant_dashboard",
    "callback_logs": [],
    "payouts": [
            {
                "id":"po_4a3Bgz6YR3cRjW6k",
                "rrn":null,
                "amount":72.5,
                "currency":"USD",
                "status":"processed"
            },
            {
                "id":"po_3cR4z6kgYR6aj3BW",
                "rrn":null,
                "amount":27.5,
                "currency":"USD",
                "status":"processed"
            }
        ]
    },
    "relationships": {
    "payout-service": {
        "data": {
        "type": "payout-services",
        "id": "payment_card_usd"
        }
    },
    "payout-method": {
        "data": {
        "type": "payout-methods",
        "id": "payment_card"
        }
    },
    "customer": {
        "data": null
    }
    },
    "links": {
    "self": "/api/payout-invoices/cpoi_sIzOuMKJg98J22NC"
    }
  }
}

Тіло запиту Callback містить тіло відповідної операції інвойсу.

Статуси інвойсів описані в посібниках:

Перевірка автентичності

Spoynt підписує дані, використовуючи ключі в хедері запиту X-Signature.

Алгоритм генерування підпису (PHP)

<?php
$secret="yourPrivateKey";    
$callbackData='{"data":{"type":"payment-invoices","id":"cpi_exampleID","attributes":{"serial_number":"exampleID","status":"processed","resolution":"ok","moderation_required":false,"amount":1000,"payment_amount":1000,"currency":"USD","service_currency":"USD","reference_id":"yourReferenceId","test_mode":true,"fee":38,"deposit":962,"processed":1647077297,"processed_amount":1000,"refunded_amount":null,"processed_fee":38,"processed_deposit":962,"metadata":[],"flow_data":{"action":"https:\/\/pay.example.com\/hpp\/cgi_exampleId","method":"GET","params":[],"metadata":{"sid":"cgi_exampleId","token":"bearerToken-for-H2H-api-auth"}},"flow":"hpp","payment_flow":"charge","created":1647077285,"updated":1647077297,"payload":{"token":"token-if-tokenize-true","auth_type":"card","client_ip":"192.168.0.1","payment_card":{"last":"0000","mask":"512381******0000","brand":null,"first":"512381","holder":"Test Customer","network":"mastercard","expiry_year":"99","issuer_name":"FIRST DATA CORPORATION","expiry_month":"09","issuer_country":"US"}},"description":null,"descriptor":null,"callback_url":"https:\/\/your.callback.url","return_url":null,"return_urls":{"fail":"https:\/\/your.fail-return.url","pending":"https:\/\/your.default-return.url","success":"https:\/\/your.success-return.url"},"original_data":null,"rrn":null,"approval_code":null,"reserved_amount":null,"reserve_expires":null,"unreserved":null,"source":"merchant_api","callback_logs":[],"charged_back_amount":null,"resolution_message":null,"hpp_url":"https:\/\/api.example.com\/hpp?cpi=cpi_exampleID"},"relationships":{"payment-service":{"data":{"type":"payment-services","id":"payment_card_usd_hpp"}},"payment-method":{"data":{"type":"payment-methods","id":"payment_card"}},"customer":{"data":{"type":"customers","id":"cus_exampleID"}},"active-payment":{"data":{"type":"payments","id":"pay_exampleID"}}},"links":{"self":"\/api\/payment-invoices\/cpi_exampleID"}},"included":[{"type":"customers","id":"cus_exampleID","attributes":{"reference_id":"example-customer-id","email":null,"name":null,"phone":null,"description":null,"created":1646833439,"metadata":[],"avatar":"https:\/\/www.gravatar.com\/avatar\/exampleAvatarID?s=20&d=mm&r=g","archived":false,"processing_options":{"payment_enabled":true,"payout_enabled":true},"address":{"street":null,"country":null,"region":null,"city":null,"full_address":null,"post_code":null}},"relationships":{"commerce-account":{"data":{"type":"commerce-accounts","id":"coma_exampleID"}}}}]}';
$signature = base64_encode(sha1($secret . $callbackData . $secret, true));

echo $signature;
В прикладі вище:

$secret — бойовий ("Live key") або тестовий ("Test key") секретний (приватний) ключ, який знаходиться в налаштуваннях акаунту;

$callbackData — неформатований JSON тіла отриманого callback.

$signature — алгоритм генерування.

Щоб переконатися в достовірності джерела, згенеруйте підпис, використовуючи відповідний ключ і raw JSON тіло Callback.

В результаті ви отримаєте стрічку base64 вигляду:

B86Af35b/IfM0z0rGROHw5gVw14=

яка повинна бути аналогічною значенню підпису в хедері Callback.

Перевищення часу очікування (тайм-аут)

Spoynt виділяє три типи тайм-аутів для Callbacks:

  1. Тайм-аут з'єднання (Connection Timeout): граничний час для встановлення початкового з'єднання з HTTP-сервером URL Callbacks.
  2. Тайм-аут читання (Read Timeout): граничний час повідомлення про отримання даних HTTP сервером після встановлення з'єднання.
  3. Загальний тайм-аут надсилання Callbacks (Execution Timeout): на додаток до попередніх Spoynt також перевіряє загальний час виконання Callbacks.

Значення тайм-аутів:

Тип Для тестового з'єднання Для бойового з'єднання
Connection Timeout 10,000 мс 20,000 мс
Read Timeout 10,000 мс 20,000 мс
Execution Timeout 20,000 мс 60,000 мс

Доставка Calbacks та автоповтор відправки

Подальші дії визначаються за HTTP-кодом, отриманим у відповіді на відправку Callbacks:

Код значення Подальші дії системи
200 Callback успішно доставлено Повторне відправлення не потрібно, наступні заплановані спроби доставки анулюються
429 Занадто багато запитів, Callback не прийнято Повторне відправлення примусово зупинено, наступні заплановані спроби доставки анулюються

Будь-який інший HTTP-код у відповіді означає, що запит не доставлено. За замовчуванням запит повторно надсилається із проміжком очікування між спробами:

  • 1-й повтор запиту буде відправлено через 1 хвилину після початкової спроби;
  • 2-й повтор - через 2 хвилини після 1-го повтору;
  • 3-й - через 3 хвилини після 2-го;
  • 4-й - через 4 хвилини після 3-го;
  • 5-й - через 5 хвилин після 4-го;
  • і 6-й - через 6 хвилин після 5го.
  • і т.д. до 100 спроб або до отримання 200 або 429 HTTP-коду.

Існує можливість налаштування інтервалу відправлення та кількості спроб

Надіслати запит нашій службі підтримки , щоб ми разом підібрали найбільш підходящий варіант.

Note

Якщо ви хочете синхронізувати дані негайно, можна перенаправити запит з панелі керування. Для цього потрібно перейти до огляду транзакції, вибрати вкладку Callbacks та кнопку Відправити заново.

Resend Callback

Дублювання

Через повторне відправлення Callbacks є ймовірність, що програма отримає ті самі дані кілька разів. Ви можете переконатися в ідемпотентності операції (властивості об'єкта або операції при повторному застосуванні операції до об'єкта давати той самий результат, що і при першому), виявивши такі дублікати даних програми.

Це не є проблемою, якщо програма визначає ідемпотентність. Для контролю використовуйте параметр id даних запиту Callbacks, т.к. його значення є унікальним для операції.

Пакетна обробка

Ми пов'язуємо Callbacks для найближчих статусів. Так, якщо платіж відразу ж перейшов зі статусу created (створений) у статус pending (в обробці) та у статус processed (оброблений), ви отримаєте лише один Callback з останнім за часом статусом (тобто processed).

Перевага такого підходу: можливість уникнути перевантаження ваших серверів HTTP запитами та позбавити вашу програму необхідності ускладнювати логіку взаємодії з послідовними змінами статусу. Ваша програма повинна піклуватися лише останній статус об'єкта.

Доставка не по порядку

Callbacks можуть приходити не по порядку через проблеми мережі або надсилання. Ви все одно можете встановити правильну послідовність подій, орієнтуючись на атрибут updated в Callbacks - часову мітку у форматі Timestamp.

IP-адреси

Для підвищення безпеки взаємодії між платформою Spoynt та вашим сервером, необхідно використовувати контроль IP-адрес.

Детальніше про домени та IP адреси →