Skip to Content
개발자퀵스타트

퀵스타트

Test 키로 결제를 만들고 웹훅으로 결과를 받는 순서예요.

AI 코딩 도구로 시작하기

https://docs.payri.kr/llms-full.txt 를 읽고 내 앱에 PayRi 결제를 연동해줘. 서버에서 Checkout Session을 만들어 결제창으로 보내고, 결제가 끝나면 successUrl로 돌아오게 해줘. order.paid 웹훅은 서명을 검증해서 받아줘. 먼저 test 키로 테스트 결제부터 웹훅 수신까지 확인해줘. API 키와 웹훅 시크릿은 환경변수 PAYRI_API_KEY, PAYRI_WEBHOOK_SECRET 에 있어.

연동하기

01
키와 도메인 준비

셀러 콘솔 외부 연동에서 checkout:write 권한의 Test API 키를 만들고, 한 번만 보이는 키를 PAYRI_API_KEY에 저장해요.
같은 메뉴에서 앱 도메인을 리디렉트 허용 목록에 등록해요.

02
결제 세션 만들고 결제창으로 보내기

서버에서 Checkout Session을 만들고 응답의 url로 구매자를 보내요.

curl -X POST https://api.payri.kr/v1/checkout/sessions \ -H "Authorization: Bearer $PAYRI_API_KEY" \ -H "Idempotency-Key: checkout-order-123" \ -H "Content-Type: application/json" \ -d '{ "productId": "prod_88x", "successUrl": "https://app.example.com/pay/complete", "cancelUrl": "https://app.example.com/cart", "metadata": { "accountId": "acct_123" } }'

구독 상품은 planId와 interval을 함께 보내요.
요청을 다시 보낼 때는 같은 Idempotency-Key를 써요.

03
웹훅 받기

외부 연동에서 Test 웹훅 엔드포인트를 만들어 order.paid를 선택하고, 시크릿을 PAYRI_WEBHOOK_SECRET에 저장해요.

import express from 'express' import { Webhook } from 'standardwebhooks' const app = express() const webhook = new Webhook(process.env.PAYRI_WEBHOOK_SECRET) app.post('/webhooks/payri', express.raw({ type: 'application/json' }), async (req, res) => { let event try { event = webhook.verify(req.body, { 'webhook-id': req.get('webhook-id'), 'webhook-timestamp': req.get('webhook-timestamp'), 'webhook-signature': req.get('webhook-signature'), }) } catch { return res.sendStatus(400) } if (event.type === 'webhook.test') { return res.sendStatus(204) } if (event.type === 'order.paid') { // event.id를 UNIQUE 키로 저장하고, 처음 보는 id만 작업 큐에 넣어요. await enqueueOnce(event.id, event) } return res.sendStatus(202) })

서명은 JSON으로 파싱하기 전 원본 본문으로 검증하고, 이벤트 id로 중복을 걸러요.

04
테스트 결제로 확인

결제창에서 성공을 고르면 successUrl에 order_id·session_id가 붙어 돌아오고, 웹훅으로 order.paid가 와요.
권한 부여 같은 처리는 복귀가 아니라 order.paid를 기준으로 해요.

05
Live 전환

Live 키와 Live 웹훅 엔드포인트를 따로 만들어 두 환경변수를 바꾸고, 운영 전환 체크리스트를 확인해요.

막히면

증상해결
400 RETURN_URL_NOT_ALLOWED리디렉트 허용 목록에 앱 도메인을 등록해요.
400 VALIDATION_FAILEDIdempotency-Key가 빠졌거나 1~255자를 벗어났어요.
403 API_KEY_SCOPE_MISSINGAPI 키에 checkout:write 권한을 줘요.
409 IDEMPOTENCY_KEY_CONFLICT같은 키를 다른 본문에 썼어요. 새 요청에는 새 키를 써요.
409 PUBLIC_CONTACT_VERIFICATION_REQUIRED스토어 공개 연락처를 인증해요.
웹훅이 안 와요API 키와 웹훅 엔드포인트의 mode가 같은지, order.paid를 선택했는지 확인해요.

그 밖의 오류는 에러 코드에서 확인해요.

Last updated on