Обзор
Что это
Принимайте платежи Apple Pay через MONDO
Вам Нужно
MONDO Идентификатор аккаунта + Секретный ключ
Что Вы Отправляете
Apple Pay токен + сумма + валюта
Что Вы Получаете
ЗАВЕРШЕНО или ОТКЛОНЕНО
Как это работает
Опция А: На своем сервере
Вы отображаете кнопку Apple Pay на вашем сайте и отправляете нам токен
Опция B: MONDO-Hosted
Мы всё сделаем - просто направьте вашего клиента к нам
Быстрый запуск (самостоятельный хостинг)
POST https://server-to-server.getmondo.co/payment/
{
"company_account_id": "your_id",
"gateway_secret_key": "your_key",
"apple_pay_token": { /* from Apple Pay JS */ },
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"live_or_sandbox": "sandbox"
}
О Apple Pay
Apple Pay предоставляет быстрый, безопасный и конфиденциальный способ оплаты для клиентов. С MONDO в качестве вашего провайдера платежных услуг (PSP), вы можете принимать Apple Pay, не нуждаясь в собственном аккаунте разработчика Apple.
MONDO как ваш PSP
- ✓ MONDO владеет идентификатором торговца Apple
- ✓ MONDO управляет сертификатами Apple Pay
- ✓ MONDO обрабатывает проверку продавцов
- ✓ MONDO расшифровывает и обрабатывает платежные токены
Управление токенами — Кто что делает?
Apple Pay использует сквозное шифрование для защиты данных владельцев карт. Вот как распределяются обязанности:
| Apple (Устройство клиента) | Генерирует зашифрованный платежный токен, содержащий данные карты, криптограмму и данные аутентификации |
| Вы (Продавец) | Передайте зашифрованный токен напрямую в MONDO через параметр apple_pay_token — не пытайтесь расшифровать |
| МОНДО (PSP) | Расшифровывает токен с использованием нашего сертификата обработки платежей Apple Pay и осуществляет платеж через CardCorp |
Выберите метод интеграции
📋 Предварительные условия
- ✓ Идентификатор партнёра - Ваш уникальный идентификатор аккаунта MONDO
- ✓ Партнерский секретный ключ - Ваш API ключ аутентификации
- ✓ HTTPS - Ваш сайт должен использовать HTTPS
⚠️ Требуется проверка домена
Ваш домен должен быть зарегистрирован в Apple через MONDO. Это одноразовая настройка.
- Перейти GETMONDO.CO
- Login → Developer → Apple Pay → Add Apple Pay Domain
🔄 Платежный процесс
На вашем сайте
Родной интерфейс Apple Pay
Ваш JS вызывает конечную точку проверки MONDO
Face ID / Touch ID
POST to /payment/ with apple_pay_token
Пользователь перенаправлен на URL успеха/неудачи
🔗 API-конечная точка
Точка проверки продавца
Параметры проверки продавца
| Параметр | Тип | Требуется | Описание |
|---|---|---|---|
| validationURL | string | ✓ Да | URL, предоставленный Apple в onvalidatemerchant событие |
| company_account_id | string | ✓ Да | Ваш идентификатор партнёрского аккаунта MONDO |
| gateway_secret_key | string | ✓ Да | Ваш секретный ключ MONDO Partner |
| domain_name | string | ○ Условный | Ваш домен Apple Pay (например, paynow.yoursite.com). Требуется для вызовов сервер-сервер, когда заголовок Origin браузера недоступен. Не требуется при вызове напрямую из браузера. |
Если ваш сервер выполняет проксирование вызова проверки продавца (т.е. ваш сервер вызывает MONDO, а не браузер напрямую), вы должны включить
domain_name установлено для домена, где отображается ваша кнопка Apple Pay. Это гарантирует соответствие сессии Apple Pay домену вашей страницы оплаты. 📝 Требуемые параметры (Обработка платежей)
| Параметр | Тип | Описание |
|---|---|---|
| company_account_id | string | Ваш идентификатор партнёрского аккаунта MONDO |
| gateway_secret_key | string | Ваш секретный ключ MONDO Partner |
| apple_pay_token | object | Зашифровано токен из event.payment.token — pass directly to MONDO as-is (не расшифровывать) |
| transaction_amount | decimal | Сумма платежа (напр., 99.99) |
| transaction_currency_iso3 | string | Код валюты (EUR, USD, GBP) |
| cardholder_email_address | string | Электронная почта клиента |
Дополнительные параметры
| Параметр | Описание |
|---|---|
| partner_return_url_completed | URL для перенаправления после успешной оплаты |
| partner_return_url_rejected | URL для перенаправления отклонённого платежа |
| partner_webhook_url | URL для вебхук-уведомлений |
| live_or_sandbox | live или sandbox |
📤 Ответ API
Оплата через Apple Pay обрабатывается немедленно. Ответ содержит окончательный статус транзакции:
{
"status": "success",
"transaction_status": "COMPLETED",
"gateway_session_id": "73d68b79579eeaa4a1f35f667509ba19",
"transaction_id": "37819a4707f3736b6fb42148d98f05ab",
"gateway_message": "Transaction succeeded",
"redirect_url": "https://yoursite.com/success?gateway_session_id=...&payment_status=COMPLETED"
}
Поля ответа
| Поле | Описание |
|---|---|
| status | success или error |
| transaction_status | COMPLETED или REJECTED |
| gateway_session_id | Уникальный идентификатор сессии для этой транзакции |
| transaction_id | Уникальный идентификатор транзакции - используйте его для сопоставления с обратными вызовами |
| gateway_message | Сообщение о состоянии |
| redirect_url | URL для перенаправления пользователя после оплаты (необязательно - только для UX) |
В отличие от платежей картой, требующих перенаправления 3D Secure, транзакции через Apple Pay обрабатываются мгновенно. Оплата уже завершена к моменту получения ответа.
🍎 Интеграция Apple Pay JS
Шаг 1: Добавить кнопку Apple Pay
<apple-pay-button buttonstyle="black" type="plain" locale="en" onclick="startApplePayPayment()"></apple-pay-button>
Шаг 2: Проверить наличие
if (window.ApplePaySession && ApplePaySession.canMakePayments()) {
document.getElementById('apple-pay-button').style.display = 'block';
}
Шаг 3: Завершение реализации
async function startApplePayPayment() {
const paymentRequest = {
countryCode: 'US',
currencyCode: 'EUR',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa', 'masterCard'],
total: { label: 'Your Company', amount: '99.99', type: 'final' }
};
const session = new ApplePaySession(3, paymentRequest);
// Merchant Validation
session.onvalidatemerchant = async (event) => {
const resp = await fetch('https://server-to-server.getmondo.co/payment/apple_pay_validate_merchant.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
validationURL: event.validationURL,
company_account_id: 'YOUR_ACCOUNT_ID',
gateway_secret_key: 'YOUR_SECRET_KEY',
domain_name: 'your-domain.com' // Required for server-to-server; optional if browser calls directly
})
});
session.completeMerchantValidation(await resp.json());
};
// Payment Authorization - Apple provides ENCRYPTED token in event.payment.token
// IMPORTANT: Pass the token directly to MONDO - do NOT attempt to decrypt it
session.onpaymentauthorized = async (event) => {
const resp = await fetch('https://server-to-server.getmondo.co/payment/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
company_account_id: 'YOUR_ACCOUNT_ID',
gateway_secret_key: 'YOUR_SECRET_KEY',
apple_pay_token: event.payment.token, // Encrypted token - MONDO decrypts
transaction_amount: '99.99',
transaction_currency_iso3: 'EUR',
cardholder_email_address: 'customer@example.com',
partner_return_url_completed: 'https://yoursite.com/success',
partner_return_url_rejected: 'https://yoursite.com/failed',
live_or_sandbox: 'live'
})
});
const result = await resp.json();
if (result.transaction_status === 'COMPLETED') {
session.completePayment(ApplePaySession.STATUS_SUCCESS);
// Payment already processed - redirect is optional for user experience
if (result.redirect_url) {
window.location.href = result.redirect_url;
}
} else {
session.completePayment(ApplePaySession.STATUS_FAILURE);
if (result.redirect_url) {
window.location.href = result.redirect_url;
}
}
};
session.begin();
}
Режимы тестирования
MONDO поддерживает два режима тестирования. Понимание различий критически важно для успешной интеграции.
Что происходит
- ✅ Структура токена проверена
- ✅ Все обязательные поля проверены
- ⏭️ Расшифровка пропущена (возвращены тестовые данные)
- ⏭️ Вызов API CardCorp пропущен
- ✅ Платеж выполнен
Что происходит
- ✅ Структура токена проверена
- ✅ Все обязательные поля проверены
- ✅ Реальное криптографическое дешифрование
- ✅ Обработка API Real CardCorp
- ✅ Реальные деньги списываются
🎯 Почему SANDBOX Требует Одинаковую Структуру Токена
Этот дизайн гарантирует, что при переключении с SANDBOX на LIVE ваша интеграция будет работать сразу без изменений в коде.
⚙️ Установка режима
Включить live_or_sandbox параметр в вашем запросе API:
{
"company_account_id": "your_account_id",
"gateway_secret_key": "your_secret_key",
"apple_pay_token": { ... },
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"live_or_sandbox": "sandbox" // or "live" for production
}
🎭 Песочница: Принудительный результат транзакции
В РЕЖИМЕ ПЕСОЧНИЦЫ вы можете принудительно задать конкретный результат транзакции для тестирования:
| Параметр | Значение | Результат |
|---|---|---|
| sandbox_force_transaction_status | COMPLETED |
✅ Оплата подтверждена |
| sandbox_force_transaction_status | REJECTED |
❌ Оплата отклонена |
Структура токена Apple Pay
Токен Apple Pay должен иметь следующую структуру. Это одинаково для режимов SANDBOX и LIVE.
"***") приведет к ошибке, даже в режиме SANDBOX. Требуемая структура токена
{
"paymentData": {
"version": "EC_v1",
"data": "BASE64_ENCRYPTED_PAYMENT_DATA",
"signature": "BASE64_SIGNATURE",
"header": {
"ephemeralPublicKey": "BASE64_EPHEMERAL_KEY",
"publicKeyHash": "BASE64_PUBLIC_KEY_HASH",
"transactionId": "UNIQUE_TRANSACTION_ID"
}
},
"paymentMethod": {
"displayName": "Visa 1234",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "APPLE_TRANSACTION_ID"
}
Описания полей
| Поле | Требуется | Описание |
|---|---|---|
| paymentData.version | ✓ | Всегда EC_v1 |
| paymentData.data | ✓ | Base64 зашифрованные платежные данные от Apple |
| paymentData.signature | ✓ | Base64 подпись для проверки |
| paymentData.header.ephemeralPublicKey | ✓ | Base64 временный публичный ключ |
| paymentData.header.publicKeyHash | ✓ | Base64 хеш публичного ключа продавца |
| paymentData.header.transactionId | ✓ | Уникальный идентификатор транзакции |
| paymentMethod.network | ○ | Сеть карт (Visa, Mastercard, Amex) |
| paymentMethod.displayName | ○ | Отображаемое имя из Apple Wallet |
✓ = Требуется | ○ = Рекомендуемые
Тестовый Токен
Скопируйте этот токен для тестирования в SANDBOX. Зашифрованные значения могут быть не настоящими - проверяется только структура.
{
"paymentData": {
"version": "EC_v1",
"data": "c2FuZGJveF9lbmNyeXB0ZWRfZGF0YV8xNzAyMjU2MDAwMDAw",
"signature": "c2FuZGJveF9zaWduYXR1cmVfMTcwMjI1NjAwMDAwMA==",
"header": {
"ephemeralPublicKey": "c2FuZGJveF9lcGhlbWVyYWxfa2V5XzE3MDIyNTYwMDAwMDA=",
"publicKeyHash": "c2FuZGJveF9wdWJsaWNfa2V5X2hhc2g=",
"transactionId": "SANDBOX_TXN_1702256000000_a1b2c3d4e5f6"
}
},
"paymentMethod": {
"displayName": "Visa 4242",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "SANDBOX_TXN_1702256000000_a1b2c3d4e5f6"
}
Распространённые ошибки токенов
| Ошибка | Причина | Решение |
|---|---|---|
| Invalid token format | Токен не является объектом JSON | Отправить токен как объект, а не строку |
| Missing paymentData | Токен не имеет свойства paymentData | Включить полный токен из Apple Pay JS |
| Missing header fields | Отсутствует ephemeralPublicKey, publicKeyHash или transactionId | Убедитесь, что все заголовочные поля присутствуют |
Откуда берётся токен?
В режиме LIVE токен поступает из Apple Pay JS, когда пользователь авторизует платеж:
session.onpaymentauthorized = (event) => {
// This is the token you send to MONDO
const token = event.payment.token;
// Send to MONDO API
fetch('/payment/', {
body: JSON.stringify({
apple_pay_token: token, // Pass the entire token object
...
})
});
};
Статус транзакции
Понимание статусов транзакций и способов их запроса необходимо для полной интеграции.
Итоговые статусы транзакций
Это возможные окончательные статусы, которые вы получите через вебхук или при запросе к точке /details:
Промежуточный статус
Транзакция создана, но еще обрабатывается. Это может произойти, когда:
- Пользователь проходит аутентификацию 3D Secure
- Оплата обрабатывается платежной системой
- Пользователь отменил платежный процесс
Когда следует запросить статус транзакции?
- Вы не получили вебхук в ожидаемое время (например, 5 минут)
- Вам нужно вручную проверить статус транзакции
- Ваш конечный точка webhook была временно недоступна
Статус транзакции
Чтобы проверить статус транзакции, отправьте POST-запрос на конечную точку details:
Параметры запроса
| Параметр | Требуется | Описание |
|---|---|---|
| company_account_id | ✓ | Ваш идентификатор партнёрского аккаунта MONDO |
| gateway_secret_key | ✓ | Ваш секретный ключ MONDO Partner |
| gateway_session_id | ✓ | Идентификатор сессии, полученный из первоначального запроса на оплату |
Пример запроса
curl -X POST https://server-to-server.getmondo.co/details/ \
-H "Content-Type: application/json" \
-d '{
"company_account_id": "your_account_id",
"gateway_secret_key": "your_secret_key",
"gateway_session_id": "sess_abc123xyz"
}'
Пример ответа
{
"success": true,
"transaction_status": "COMPLETED",
"gateway_session_id": "sess_abc123xyz",
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"card_last_4_digits": "4242",
"card_brand": "VISA",
"gateway_result_code": "000.000.000",
"gateway_result_description": "Transaction succeeded",
"created_at": "2024-12-10T22:30:00Z",
"completed_at": "2024-12-10T22:31:15Z"
}
Получение обновлений статуса
Есть два способа получить окончательный статус транзакции:
| Метод | Как это работает | Когда использовать |
|---|---|---|
| Webhook Рекомендуемые | MONDO отправляет POST-запрос вашему partner_webhook_url |
Основной метод - автоматический, в реальном времени |
| Redirect URL | Пользователь перенаправлен на ваш partner_return_url_completed или partner_return_url_rejected |
Для подтверждения пользователем |
| Query /details | Вы отправляете POST-запрос для проверки статуса | Запасной вариант, если вебхук не получен |
Если транзакция остаётся НЕЗАВЕРШЁННОЙ
Если транзакция остаётся в статусе ИНИЦИИРОВАНА более 15 минут, это вероятно означает:
- Пользователь отказался от проверки 3D Secure
- Пользователь закрыл браузер во время оплаты
- Произошла ошибка сети во время обработки
Действие: Запросите /details endpoint для получения текущего статуса. Эти транзакции в конечном итоге завершатся тайм-аутом и перейдут в статус FAILED или CANCELED.