개요

무엇인가요

MONDO를 통해 Apple Pay 결제 수락

필요한 것들

MONDO 계정 ID + 비밀 키

보낸 사진

Apple Pay 토큰 + 금액 + 통화

받는 것

완료됨 또는 거부됨 상태

작동 방식

고객
Apple Pay
당신
MONDO
완료

옵션 A: 자체 호스팅

Apple Pay 버튼을 사이트에 표시하고 토큰을 전송하세요

옵션 B: MONDO-주최

모든 것을 처리합니다 - 고객을 저희에게로 리디렉션하세요

빠른 시작 (자체 호스팅)

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 개발자 계정 없이도 Apple Pay를 수락할 수 있습니다.

MONDO가 당신의 PSP로

  • MONDO가 Apple Merchant ID를 소유합니다
  • MONDO는 Apple Pay 인증서를 관리합니다
  • MONDO가 상인 검증을 처리합니다
  • MONDO는 결제 토큰을 해독하고 처리합니다
필요 없는 것: Apple 개발자 계정 없음, Apple 판매자 ID 없음, 관리할 인증서 없음.

토큰 처리 - 누가 무엇을 하나요?

Apple Pay는 카드 소유자 데이터를 보호하기 위해 종단 간 암호화를 사용합니다. 책임이 어떻게 나뉘어져 있는지는 다음과 같습니다:

애플 (고객의 기기) 암호화된 결제 토큰 생성 - 카드 데이터, 암호문, 인증 세부 정보 포함
당신 (상인) 암호화된 토큰을 apple_pay_token 파라미터를 통해 MONDO에 직접 전달하세요복호화를 시도하지 마세요
몬도 (PSP) 토큰을 해독하고 Apple Pay 결제 처리 인증서를 사용하여 CardCorp와 결제를 처리합니다
중요: 카드 번호를 직접 보거나 다루지 않습니다. Apple로부터 받은 토큰은 암호화되어 있으며, 저희 MONDO의 상인 인증서를 사용해서만 복호화할 수 있습니다.

통합 방법 선택

최적: Apple Pay 버튼의 모양과 사용자 경험을 직접 제어하세요.

📋 필수 조건

  • 파트너 계정 ID - 고유한 MONDO 계정 식별자
  • 파트너 비밀 키 - API 인증 키
  • HTTPS - HTTPS를 사용해야 합니다

⚠️ 도메인 확인 필요

Apple을 통해 MONDO에 도메인을 등록해야 합니다. 이는 일회성 설정입니다.

  1. 이동 GETMONDO.CO
  2. LoginDeveloperApple PayAdd Apple Pay Domain

🔄 결제 흐름

1
사용자가 Apple Pay 버튼을 클릭함
웹사이트에서
2
Apple Pay 시트 열기
네이티브 애플 페이 인터페이스
3
상인 검증
JS가 MONDO의 검증 엔드포인트를 호출합니다
4
사용자 인증
Face ID / Touch ID
5
MONDO로 토큰 전송됨
POST to /payment/ with apple_pay_token
6
3D 보안 & 리디렉트
사용자가 성공/실패 URL로 리디렉션되었습니다

🔗 API 엔드포인트

POST https://server-to-server.getmondo.co/payment/

상인 검증 엔드포인트

POST https://server-to-server.getmondo.co/payment/apple_pay_validate_merchant.php

상인 검증 매개변수

파라미터유형필요함설명
validationURLstring✓ 예Apple에서 제공한 URL onvalidatemerchant 이벤트
company_account_idstring✓ 예귀하의 MONDO 파트너 계정 ID
gateway_secret_keystring✓ 예당신의 MONDO 파트너 비밀 키
domain_namestring○ 조건부Apple Pay 도메인(예: paynow.yoursite.com). 브라우저 Origin 헤더를 사용할 수 없는 서버 간 호출에 필요합니다. 브라우저에서 직접 호출하는 경우 필요하지 않습니다.
서버 간 통합 참고:
백엔드가 상인 검증 호출을 프록시하는 경우(즉, 서버가 브라우저 대신 MONDO를 호출하는 경우), 반드시 포함해야 합니다 domain_name Apple Pay 버튼이 표시되는 도메인으로 설정하세요. 이렇게 하면 Apple Pay 세션이 결제 페이지 도메인과 일치하게 됩니다.

📝 필수 매개변수 (결제 처리)

파라미터유형설명
company_account_idstring귀하의 MONDO 파트너 계정 ID
gateway_secret_keystring당신의 MONDO 파트너 비밀 키
apple_pay_tokenobject암호화됨 토큰 발급 완료 event.payment.token — pass directly to MONDO as-is (암호 해독 금지)
transaction_amountdecimal결제 금액 (예: 99.99)
transaction_currency_iso3string통화 코드 (EUR, USD, GBP)
cardholder_email_addressstring고객 이메일

선택적 매개변수

파라미터설명
partner_return_url_completed성공적인 결제 리디렉션 URL
partner_return_url_rejected거절된 결제 리디렉션 URL
partner_webhook_url웹훅 알림 URL
live_or_sandboxlive 또는 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"
}

응답 필드

필드설명
statussuccess 또는 error
transaction_statusCOMPLETED 또는 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는 두 가지 테스트 모드를 지원합니다. 차이점을 이해하는 것이 성공적인 통합에 중요합니다.

SANDBOX 테스트용

무슨 일이 일어나나요

  • ✅ 토큰 구조가 검증되었습니다
  • ✅ 모든 필수 필드가 확인되었습니다
  • ⏭️ 암호 해독이 생략됨 (모의 데이터 반환)
  • ⏭️ CardCorp API 호출이 건너뛰어졌습니다
  • ✅ 전체 결제 과정이 실행되었습니다
💡
핵심 포인트: 적절한 구조의 토큰을 보내야 합니다 - 라이브 모드에 필요한 동일한 형식입니다.
LIVE 제작용

무슨 일이 일어나나요

  • ✅ 토큰 구조가 검증되었습니다
  • ✅ 모든 필수 필드가 확인되었습니다
  • ✅ 실제 암호 해독
  • ✅ Real CardCorp API 처리
  • ✅ 실제 금액이 청구됩니다
🔒
핵심 포인트: 실제 기기의 실제 Apple Pay 토큰으로만 LIVE 모드 사용하세요.

🎯 SANDBOX가 동일한 토큰 구조를 요구하는 이유

이 디자인은 SANDBOX에서 LIVE로 전환할 때 코드 변경 없이 통합이 즉시 작동하도록 보장합니다.

🧪
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 모드에서는 테스트를 위해 특정 거래 결과를 강제로 적용할 수 있습니다:

파라미터가치결과
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.dataApple에서 암호화된 Base64 결제 데이터
paymentData.signatureBase64 서명 확인
paymentData.header.ephemeralPublicKeyBase64 일시적 공개 키
paymentData.header.publicKeyHash상인의 공개 키 Base64 해시
paymentData.header.transactionId고유 거래 식별자
paymentMethod.network카드 네트워크 (Visa, Mastercard, Amex)
paymentMethod.displayNameApple 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 엔드포인트를 조회할 때 받게 될 가능한 최종 상태입니다:

COMPLETED
결제 성공
REJECTED
처리기에 의해 결제 거절됨
CANCELED
사용자가 결제를 취소했습니다
FAILED
기술적 오류 발생

중간 상태

INITIATED

거래가 생성되었으나 아직 처리 중입니다. 다음과 같은 경우에 발생할 수 있습니다:

  • 사용자가 3D 보안 인증을 완료 중입니다
  • 카드 네트워크에서 결제 처리 중입니다
  • 사용자가 결제 과정을 중단했습니다

언제 거래 상태를 조회해야 하나요?

최선의 방법: 항상 웹훅을 주요 알림 방법으로 사용하세요. 다음의 경우에만 /details 엔드포인트를 대체 방법으로 조회하세요:
  • 예상 시간 내에 웹훅을 받지 못했습니다 (예: 5분)
  • 거래 상태를 수동으로 확인해야 합니다
  • 웹후크 엔드포인트가 일시적으로 사용할 수 없습니다

거래 상태 조회

거래 상태를 확인하려면 세부 정보 엔드포인트에 POST 요청을 하세요:

POST https://server-to-server.getmondo.co/details/

요청 매개변수

파라미터 필요함 설명
company_account_id 귀하의 MONDO 파트너 계정 ID
gateway_secret_key 당신의 MONDO 파트너 비밀 키
gateway_session_id 초기 결제 요청에서 반환된 세션 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분 이상 INITIATED 상태로 남아 있다면, 다음을 의미할 가능성이 높습니다:

  • 사용자가 3D 보안 도전을 포기했습니다
  • 사용자가 결제 중에 브라우저를 닫았습니다
  • 처리 중 네트워크 문제가 발생했습니다

동작: /details 엔드포인트를 조회하여 현재 상태를 확인하세요. 이 트랜잭션은 결국 타임아웃되어 FAILED 또는 CANCELED 상태로 변경됩니다.