목차
Stripe는 모든 것에 대해 메일을 보내고, 그래서 결국 아무것도 알리지 못합니다. 결제 성공, 구독 갱신 실패, 지불 거절이 전부 같은 받은편지함에 같은 모습으로 도착하고, 당신이 읽을 때쯤이면 그 셋의 차이는 이미 사라져 있습니다.
해법은 알림을 더 늘리는 게 아닙니다. 각 Stripe 이벤트에 실제로 걸맞은 긴급도를 주는 것입니다. 누가 결제하면 조용한 푸시, 갱신이 실패하면 시간 민감 알림, 그리고 응답 기한이 붙은 분쟁이 들어오면 전화입니다.
정말 당신이 필요한 Stripe 이벤트
모든 이벤트가 알림감은 아니고, 알림감인 것들끼리도 긴급도가 같지는 않습니다.
| Stripe 이벤트 | 왜 중요한가 | 긴급도 |
|---|---|---|
payment_intent.succeeded | 누가 결제했다. 알면 좋지만 급하지 않다. | 일반 |
invoice.payment_failed | 갱신이 실패했다. 구독이 끊기기 전 재시도 구간이 남아 있다. | 시간 민감 |
charge.dispute.created | 지불 거절. Stripe가 카드 네트워크가 정한 응답 기한을 알려 주고, 놓치면 자동으로 진다. | 전화 |
payment_intent.payment_failed | 일회성 결제 실패. 양으로 보면 유용하고, 하나씩 보면 시끄럽다. | 일반, 또는 알림 없음 |
전화를 걸 만한 건 분쟁 하나뿐입니다. 나머지는 당신이 직접 휴대폰을 집을 때까지 기다려도 됩니다. 일주일 늦게 알아챈 지불 거절은 애초에 지킬 수 없던 돈입니다.
1단계 — 긴급도별로 채널 하나씩
Echobell에서 채널 세 개를 만드세요. 긴급도는 채널 단위 설정이기 때문입니다.
- Stripe · 매출 — 일반 알림, 결제 성공용
- Stripe · 결제 실패 — 시간 민감
- Stripe · 분쟁 — 전화
각 채널 설정에서 webhook URL을 복사하세요. Stripe에서 이 셋 모두를 가리키게 됩니다.
들른 김에 각각 POST만 허용을 켜 두세요. Stripe는 항상 POST로 보내며, 이렇게 하면 링크 미리보기나 주소창 자동완성이 채널을 실수로 발동시키는 일을 막아 줍니다.
2단계 — Stripe에 엔드포인트 추가하기
Stripe 대시보드에서 Developers → Webhooks → Add endpoint로 가서 채널 URL을 붙여넣고, 그 채널이 처리해야 할 이벤트만 선택하세요.
전부를 한 엔드포인트에 몰지 말고 채널당 하나씩 만드는 편이 낫습니다. Stripe가 엔드포인트별로 이벤트를 고르게 해 주므로 라우팅이 Stripe 쪽에서 끝나고, 채널 쪽은 단순하게 유지됩니다.
굳이 엔드포인트를 하나만 쓰고 싶다면 한 채널을 가리킨 뒤 조건으로 거르세요.
type == "charge.dispute.created"
조건은 템플릿에서 쓰는 {{ }} 감싸기 없이 씁니다.
3단계 — 페이로드를 읽을 수 있게 만들기
Stripe가 보내는 JSON 본문은 대략 이런 모양입니다.
{
"type": "charge.dispute.created",
"data": {
"object": {
"amount": 4900,
"currency": "usd",
"reason": "fraudulent",
"status": "warning_needs_response"
}
}
}
그래서 채널 템플릿은 data.object 안으로 들어갑니다.
제목
분쟁: {{data.object.reason}}
본문
{{data.object.amount}} {{data.object.currency}} 분쟁 제기됨
상태: {{data.object.status}}
거의 모두가 걸리는 함정: Stripe 금액은 해당 통화의 최소 단위입니다. 4900은 49.00달러이지 4,900달러가 아닙니다. Echobell 템플릿은 값을 그대로 넣으므로, 보내기 전에 나누거나 통화를 뒤에 적고 센트로 읽으세요. 숫자가 한눈에 맞아야 한다면 나눗셈은 Stripe와 Echobell 사이에 있는 것(Worker, 자동화 도구, 직접 만든 엔드포인트)에 두세요.
매출 채널은 같은 발상을 더 짧게.
제목
+{{data.object.amount}} {{data.object.currency}}
본문
{{data.object.description}}
4단계 — 실제 결제를 기다리지 않고 테스트하기
Stripe CLI로 진짜 형태의 이벤트를 엔드포인트에 쏠 수 있습니다.
stripe trigger payment_intent.succeeded
stripe trigger charge.dispute.created
의존하기 전에 먼저 해 보세요. "당연히 있을 거라 여겼던 필드가 null로 올 때 템플릿이 어떻게 렌더링되는지" 확인하는 가장 빠른 방법이기도 합니다.
이 구성이 해 주지 않는 것
매출 앞단에 두기 전에 알아야 할 한계가 둘 있습니다.
Echobell은 Stripe 서명을 검증하지 않습니다. Stripe는 모든 웹훅에 Stripe-Signature 헤더로 서명하고, 그 검증에는 엔드포인트 시크릿이 필요합니다. Echobell의 웹훅 엔드포인트는 그 검사를 하지 않으므로 채널을 지키는 것은 URL뿐입니다. 비밀로 취급하고, POST만 허용을 켠 채로 두고, 공개 저장소나 스크린샷에 붙여넣지 마세요.
조건으로 약한 확인을 더할 수는 있습니다.
header["stripe-signature"] != ""
이건 "무언가가 Stripe 모양의 요청을 보내고 있다"는 것만 확인해 줍니다. "그게 Stripe였다"는 확인해 주지 않습니다. 위조된 알림이 (잠깐의 혼란이 아니라) 실제 피해를 낳는다면, 앞단에 직접 만든 엔드포인트를 두고 거기서 서명을 검증한 뒤 Echobell을 호출하게 하세요.
이건 알림 경로이지 장부가 아닙니다. Stripe는 실패한 웹훅 전송을 재시도하지만, 알림은 무슨 일이 있었는지에 대한 기록이 아닙니다. 대사는 알림 이력이 아니라 Stripe를 기준으로 하세요.
자주 묻는 질문
Stripe가 직접 전화를 걸어 줄 수 있나요?
없습니다. Stripe는 메일과 웹훅을 보냅니다. 전화가 되려면 전화를 걸 수 있는 무언가로 웹훅을 넘겨야 합니다.
분쟁 알림이 정말 저를 깨우나요?
채널을 전화 모드로 뒀다면 네. 수신 전화로 도착해 집중 모드와 방해 금지를 뚫고 울립니다. 중요 알림으로 iOS 집중 모드 뚫기를 참고하세요.
공동 창업자도 같은 알림을 받을 수 있나요?
가능합니다. 채널을 공유하면 구독자마다 알림 유형을 고릅니다. 같은 이벤트를 당신은 전화로, 다른 사람은 조용한 푸시로 받을 수 있습니다.
테스트 모드는요?
Stripe 테스트 모드 이벤트는 테스트 모드로 등록한 엔드포인트로만 갑니다. 그 트래픽도 보고 싶다면 양쪽 모두에 채널 URL을 등록하고, 구성이 미덥지 않다면 테스트 모드에만 등록해 두세요.
마무리
채널 셋, 엔드포인트 셋, 각각 템플릿 하나. 핵심은 Stripe로부터 알림을 받는 게 아닙니다. 그건 이미 받고 있었습니다. 핵심은 지불 거절이 영수증과 똑같아 보이는 일을 그만두게 하는 것입니다.
iPhone용 Echobell 다운로드 또는 Google Play에서 받기 후, stripe trigger charge.dispute.created를 한 번 실행해 일부러 전화를 울려 보세요.