PayPal
관리자 페이지 위치: Finance › Payment channels › PayPal (
/payments/paypal). 켜기/끄기 스위치와 수수료는 Finance › Payment channels › Fees & limits (/payments/fees)에 있습니다.
작동 내용
고객이 PayPal 잔액, 은행 계좌 또는 PayPal에 등록된 카드로 USD 지갑을 충전할 수 있습니다. 또한 고객은 NexCMP가 automatic top-up을 위해 PayPal 계정을 기억하도록 설정할 수 있습니다. PayPal을 선호하는 고객을 위해 Stripe와 함께 사용하세요.
요구 사항
| 항목 | 요구 사항 |
|---|---|
| PayPal account | USD를 받을 수 있는 PayPal 비즈니스 계정 |
| REST app | PayPal Developer Dashboard(Apps & Credentials)의 Client ID 및 Client secret을 제공하는 하나의 REST 앱. 테스트용으로는 Sandbox 탭을, 프로덕션용으로는 Live 탭을 사용하세요. |
| 네트워크 | 인터넷에서 접근 가능한 HTTPS(PayPal이 웹훅을 호출함) 및 api-m.paypal.com(라이브) 또는 api-m.sandbox.paypal.com(샌드박스) 포트 443에 대한 아웃바운드 접근. |
| Permissions | REST 앱에는 환불 및 웹훅 기능이 필요합니다. Check 대화상자에서 두 범위가 모두 있는지 확인할 수 있습니다. |
| 의존성 | 없음. |
인프라 준비
- 비즈니스 계정으로 developer.paypal.com에 로그인한 후 Apps & Credentials을(를) 엽니다.
- Sandbox(테스트) 또는 Live를 선택한 후 Create App을 클릭합니다. 예를 들어 "NexCMP"와 같이 이름을 지정합니다.
- 앱의 Client ID과(와) Secret을 복사합니다.
- 테스트를 위해 Testing Tools › Sandbox Accounts를 사용하여 Personal(구매자) 샌드박스 계정을 찾거나 생성합니다.
- 웹훅을 직접 생성할 필요가 없습니다. NexCMP가 Create webhook 버튼으로 생성합니다.
NexCMP에서 연결
- Finance › Payment channels › PayPal을 엽니다 (
/payments/paypal). - API keys에서 Mode를 선택합니다:
live(실제 결제,api-m.paypal.com) 또는sandbox(api-m.sandbox.paypal.com). - Client ID(최소 20자)와 Client secret을 붙여넣습니다.
- Check를 클릭합니다. 입력한 자격 증명을 테스트하고(저장 불필요) 연결 상태, 앱 ID, 모드, 환불 및 웹훅 스코프 포함 여부, 토큰 수명 주기를 보고합니다.
- Save를 클릭합니다.
- Webhook 카드에서 URL이
https://<your-domain>/v1/billing/paypal/webhook인지 확인하고(https여야 함), Create webhook을 클릭하여 확인합니다. NexCMP는 PayPal에 11개의 이벤트로 웹훅을 생성 또는 업데이트하도록 요청하고 반환된 Webhook ID를 저장합니다. 이 버튼은 저장된 키를 사용하므로, 방금 편집한 경우 먼저 저장하세요. - Check를 다시 클릭합니다. Webhook 행에 "exists, 11 events"가 표시되어야 합니다.
- Fees & limits를 열고 PayPal을 켠 후, PayPal fee %(기본값 4.4)와 PayPal fixed fee (cents)(기본값 30)를 요금제에 맞게 설정하고 Save channels & fees를 클릭합니다.

웹훅 이벤트
NexCMP는 다음 11개 이벤트를 등록합니다: CHECKOUT.ORDER.APPROVED, PAYMENT.CAPTURE.COMPLETED, PAYMENT.CAPTURE.PENDING, PAYMENT.CAPTURE.DECLINED, PAYMENT.CAPTURE.REFUNDED, PAYMENT.CAPTURE.REVERSED, CUSTOMER.DISPUTE.CREATED, CUSTOMER.DISPUTE.UPDATED, CUSTOMER.DISPUTE.RESOLVED, RISK.DISPUTE.CREATED, CHECKOUT.PAYMENT-APPROVAL.REVERSED.
각 웹훅은 PayPal의 서명 검증 API를 호출하여 검증되며, 한 번 저장되고 멱등성 있게 처리됩니다. NexCMP는 웹훅 본문의 금액을 절대 신뢰하지 않으며, 결제를 승인하기 전에 PayPal에서 결제 건을 가져옵니다.
확인
- Mode를
sandbox상태로 유지합니다. 포털에서 Billing › Deposit을 열고 PayPal을 선택한 다음, Continue on PayPal(또는 PayPal 버튼)을 클릭하고 샌드박스 구매자 계정으로 로그인합니다. - 결제를 승인합니다. 포털로 돌아오면 잔액이 증가하고 Finance › Billing › Top-ups에 결제가 Completed 상태로 표시됩니다.
- Payment channels › Gateway events › PayPal & USDT를 엽니다.
PAYMENT.CAPTURE.COMPLETED이벤트가 목록에 표시됩니다. - 모든 것이 정상 작동하면 Mode를
live로 전환하고 라이브 자격 증명을 입력한 후 Save를 누르고, Create webhook을 다시 클릭합니다(샌드박스 웹훅과 라이브 웹훅은 별개입니다).
한도 및 참고 사항
- 결제 완료 방식. 주문은 USD로 생성되며, 고객이 승인한 후 서버가 이를 캡처하고(멱등성 요청 ID) 지갑에 정확히 한 번 적립합니다. 고객이 브라우저를 닫는 경우에 대비해 웹훅과 10분마다 실행되는 대조 작업이 안전망 역할을 합니다.
- 보류 및 중단된 주문. 주문은 12시간 동안 열려 있을 수 있습니다. 고객은 최대 5개의 보류 중인 주문을 가질 수 있습니다(서버는
too_many_pending, HTTP 429로 응답). 24시간이 지나도 캡처되지 않은 주문은 실패로 표시됩니다. - 웹훅이 설정되지 않은 경우. Webhook ID가 저장될 때까지 패널은 모든 PayPal 웹훅에 HTTP 503으로 응답합니다. 포털을 통한 결제와 10분 주기의 대조 작업은 여전히 지갑에 적립되지만, PayPal이 웹훅으로 보고하는 내용(분쟁, 취소, 지연 결제)은 적용되지 않습니다. Create webhook을 클릭하세요.
- 저장된 PayPal 계정. 고객이 PayPal 저장을 선택하거나(또는 automatic top-up을 활성화하는 첫 번째 예치금을 완료하면) PayPal은 결제 토큰을 볼트에 저장합니다. NexCMP는 식별자와 PayPal 이메일만 보관합니다. Saved payment methods를 참조하세요.
- 환불 및 분쟁은 Stripe와 동일하게 처리됩니다. 환불 요청은 Finance › Payouts › Card refunds에서 승인하며, 분쟁이 발생하면 고객 계정이 차단되고 문제를 해결할 때까지 선불 서비스가 중지됩니다.
- 수수료. PayPal의 수수료는 자동으로 불러오지 않으며, 설정한 백분율과 고정 수수료에 따라 고객에게 표시되는 금액과 적립되는 금액이 결정됩니다. 실제 요율은 국가에 따라 다릅니다(양식에는 베트남의 경우 4.4%, 미국의 경우 3.49%로 안내됨).
Troubleshooting
| 증상 | 원인 | 해결 방법 |
|---|---|---|
| "Client ID가 너무 짧습니다" | 20자 미만이 붙여넣어짐 | 전체 Client ID를 복사합니다. |
| "Webhook URL은 반드시 https여야 합니다" | URL이 http://로 입력됨 | 공개 https:// 도메인을 사용하세요. |
| 확인에서 연결 오류 보고됨 | 잘못된 모드(샌드박스에서의 라이브 키 또는 그 반대), 잘못된 시크릿, 아웃바운드 액세스 없음 | Mode을 키 유형에 맞추고, 서버에서 curl -I https://api-m.paypal.com을(를) 테스트합니다. |
| 환불 / 웹훅 범위에 "no"가 표시됨 | REST 앱에 기능이 부족함 | PayPal Developer Dashboard의 앱에서 기능을 활성화하세요. |
| 배너 "PayPal key set, NO webhook" | 웹훅 ID 누락 | Create webhook을 클릭하세요. |
| 확인에 "Webhook not found" 표시됨 | 웹훅이 PayPal에서 삭제되었거나 다른 앱에 속해 있음 | Create webhook을 다시 클릭하세요. |
| 고객에게 PayPal이 결제를 거절했다고 안내됨 | PayPal이 해당 자금 출처를 거부함 | 고객에게 다른 결제 수단을 선택하도록 요청하세요. |
| 고객에게 "Too many pending requests"가 표시됨 | 5개의 미결제 주문 | 만료될 때까지 기다리거나 완료 처리하세요. |
| PayPal 버튼이 누락됨 | Fees & limits에서 PayPal이 꺼져 있거나 설정되지 않음 | 켜고 자격 증명을 저장하세요. |