무효화된 구매 알림을 사용하면 환불이 도착하는 순간 Google Play 서버가 접근 권한을 취소할 수 있습니다
Google Play는 구매가 환불, 차지백, 또는 무효화되는 즉시 무효화된 구매 알림을 서버로 푸시할 수 있습니다. 이 알림은 purchaseToken, orderId, productType, refundType를 담고 있으며, 의미하는 바는 단 하나, 접근 권한을 취소하라는 것입니다. 이를 읽고 연결하는 방법을 소개합니다.

핵심 요약
- 무효화된 구매 알림은 구매가 환불, 차지백, 또는 그 밖의 방식으로 무효화되는 순간 Google Play가 Cloud Pub/Sub 토픽으로 푸시하는 Real-time Developer Notification입니다. 이는 푸시 신호이며, 직접 폴링해서 가져와야 하는 것이 아닙니다.
- 이 알림은 정확히 네 개의 필드, `purchaseToken`, `orderId`, `productType`, `refundType`를 담습니다. 이것만으로 데이터베이스에서 해당 구매를 정확히 찾아, 거기에 연결된 이용 권한을 취소하기에 충분합니다.
- `productType`는 무효화된 구독일 때 `1`, 무효화된 일회성 구매일 때 `2`입니다. `refundType`는 전액 환불일 때 `1`, 수량 기반 부분 환불일 때 `2`이며, 후자는 다중 수량 일회성 구매에만 적용됩니다.
- 무효화된 구매 알림은 고객이 이미 환불을 받았다는 것을 의미합니다. Google 자체의 안내는 구매자가 더 이상 이용 권한을 보유해서는 안 되므로, 관련 콘텐츠에 대한 접근 권한을 취소하라는 것입니다.
- 무효화된 구매 알림은 켜기 전까지는 꺼져 있습니다. Play Console의 Monetization setup에서 구독과 모든 무효화된 구매, 또는 여기에 일회성 제품 이벤트를 더한 것 중 하나를 선택합니다. 두 옵션 모두 무효화된 구매를 포함합니다.
- 무효화된 구매 알림은 증거를 요구하는 두 가지 환불 흐름 중 어느 것도 아닙니다. 이것은 사후 통지입니다. 여러분의 입력을 받는 유일한 흐름은 12시간 기한이 있는 Apple의 CONSUMPTION_REQUEST와 24시간 기한이 있는 `orders.reviewrefund`를 통한 Google Play의 차지백 검토뿐입니다.
- 2026년 8월 3일부터 Google은 차지백의 구매 금액에 은행 수수료를 더한 금액을 개발자에게 전가합니다. 무효화된 구매 알림은 차지백 무효화가 도착했다는 사실을 서버가 처음 알게 되는 수단인 경우가 많으므로, 이를 연결해 두는 것이 더 이상 대금을 받지 못하는 고객에 대한 제공을 멈출 수 있게 해 줍니다.
Google Play에서의 환불은 나중에 리포트에서 발견하는 무언가일 필요가 없습니다. Google Play는 구매가 무효화되는 즉시 무효화된 구매 알림을 서버로 푸시할 수 있습니다. 구매자가 셀프 서비스 환불을 받았든, 지원 상담원이 환불을 승인했든, 은행이 차지백을 강제했든, 아니면 여러분이 취소 플래그를 켜고 주문을 직접 환불했든 마찬가지입니다. 메시지는 아주 작고, 정확한 구매를 지목하며, 단 하나의 지시를 담습니다. 이용 권한을 반환하라, 왜냐하면 대금은 이미 사라졌기 때문입니다.
무효화된 구매 알림이란 실제로 무엇인가
무효화된 구매 알림은 Google Play의 Real-time Developer Notifications, 즉 RTDN의 한 유형입니다. RTDN은 푸시 채널입니다. Google은 여러분이 소유한 Cloud Pub/Sub 토픽으로 메시지를 발행하며, 백엔드는 다음 예정된 폴링에서 알아차리는 대신 이벤트 직후에 그것을 받습니다. 이것이 오래된 풀 방식에 비한 무효화된 구매 알림의 핵심입니다. 환불을 몇 시간 뒤가 아니라 발생과 동시에 알게 됩니다.
풀 방식은 여전히 존재하며 여전히 중요합니다. Voided Purchases API를 사용하면 서버가 자체 일정에 따라 특정 기간 동안 무효화된 구매 목록을 요청할 수 있습니다. 둘은 상호 보완적입니다. 알림은 한 건의 구매가 전환되는 순간을 알려 주고, API는 대량으로 대조하고 놓친 메시지가 남긴 것을 메워 줍니다.
그것은 Real-time Developer Notification 안에 실려 도착한다
무효화된 구매 알림은 결코 단독으로 도착하지 않습니다. 그것은 DeveloperNotification 래퍼 안에 들어 있으며, 그 래퍼는 Pub/Sub 메시지의 data 필드에 단일 base64 인코딩 문자열로 전달됩니다. 핸들러는 무언가를 읽기 전에 그 문자열을 JSON으로 디코딩합니다. 래퍼는 항상 앱과 이벤트 시각을 지목하며, Google이 정의한 다섯 개 중 정확히 하나의 알림 객체를 포함합니다. 그것들은 상호 배타적이므로, voidedPurchaseNotification을 담은 메시지가 구독이나 일회성 이벤트를 함께 담는 일은 없습니다.
| 래퍼 필드 | 담는 내용 |
|---|---|
version | 알림 스키마 버전. 예를 들어 1.0 |
packageName | 이벤트가 속한 앱. 예를 들어 com.acme.app |
eventTimeMillis | 이벤트가 발생한 시각. 에포크 이후 밀리초 |
| 다섯 개의 알림 객체 중 하나 | oneTimeProductNotification, subscriptionNotification, voidedPurchaseNotification, pendingRefundReviewNotification, 또는 testNotification. 메시지당 하나만 존재한다 |
그것이 담는 네 개의 필드
래퍼를 벗겨 내면 무효화된 구매 알림 자체는 네 개의 필드입니다. 이는 의도적으로 간결합니다. 올바른 구매를 찾아 이용 권한을 조정하는 것만 필요하다면 이 넷으로 충분하며, 조치를 취하기 위해 어떤 API도 다시 호출할 필요가 없다는 것이 Google의 입장입니다.
| 필드 | 그것이 무엇인가 | 사용 방법 |
|---|---|---|
purchaseToken | 상품이 구매될 때 기기로 전달된 토큰 | 여러분의 기본 키. 권한 부여 시 저장한 구매 레코드와 대조한다 |
orderId | 구매자에게 표시되는 주문 ID. 예를 들어 GS.0000-0000-0000 | 지원과 대조를 위한 사람이 읽을 수 있는 두 번째 키 |
productType | 무효화된 항목이 구독인지 일회성 구매인지 | 올바른 취소 경로로 라우팅한다 |
refundType | 무효화가 전액 환불인지 수량 기반 부분 환불인지 | 전부 취소할지 환불된 수량만 취소할지 결정한다 |
productType는 무엇이 무효화되었는지 알려 준다
productType는 작은 정수이며, 어느 취소 경로를 취할지 결정합니다. 구독 무효화는 진행 중인 접근 권한을 되돌려야 하고, 일회성 구매 무효화는 단일 이용 권한을 제거하기만 하면 됩니다.
| `productType` 값 | 상수 | 의미 |
|---|---|---|
1 | PRODUCT_TYPE_SUBSCRIPTION | 구독 구매가 무효화되었다 |
2 | PRODUCT_TYPE_ONE_TIME | 일회성 구매가 무효화되었다 |
refundType는 얼마가 반환되었는지 알려 준다
refundType는 깔끔한 전액 취소와 부분 취소를 구분합니다. 부분 취소 경우는 제한적입니다. 그것은 다중 수량 일회성 구매에서 수량의 일부만(전부가 아니라) 환불되었을 때에만 나타납니다.
| `refundType` 값 | 상수 | 의미 |
|---|---|---|
1 | REFUND_TYPE_FULL_REFUND | 구매가 전액 무효화되었다 |
2 | REFUND_TYPE_QUANTITY_BASED_PARTIAL_REFUND | 다중 수량 구매의 일부가 무효화되었다 |
먼저 켜라, 그러지 않으면 결코 도착하지 않는다
무효화된 구매 알림은 기본적으로 흐르지 않습니다. RTDN은 Play Console에서 한 번 활성화하고, 여러분이 관리하는 Pub/Sub 토픽으로 향하게 합니다. 그 스위치는 Monetize, 그다음 Monetization setup 아래, 페이지 상단의 Real-time developer notifications 섹션에 있습니다. Enable real-time notifications를 체크하고, projects/{project_id}/topics/{topic_name} 형식으로 전체 토픽 이름을 붙여 넣은 다음, 신뢰하기 전에 Send Test Message로 파이프가 작동하는지 확인하십시오.
콘텐츠 토글이 사람들이 무효화된 구매를 놓치는 지점입니다. 두 선택지 모두 그것들을 포함하므로, 구독을 유지하면서 실수로 환불을 옵트아웃할 수는 없습니다.
- 구독과 모든 무효화된 구매에 대한 알림을 받기. 구독 이벤트와 모든 무효화된 구매를 받지만, 일회성 제품 구매 이벤트는 받지 않습니다.
- 구독과 일회성 제품에 대한 모든 알림을 받기. 위의 것에 더해
ONE_TIME_PRODUCT_PURCHASED와ONE_TIME_PRODUCT_CANCELED같은 일회성 제품 이벤트를 받습니다.

그것이 금전적으로 여러분에게 얼마의 손실을 주는가
무효화는 알림이 여러분에게 도달할 무렵에는 이미 장부에 기록된 손실입니다. 판매 가격은 사라졌고, 그 고객에게 서비스를 제공하기 위해 쓴 것도 마찬가지입니다. 그들이 이미지를 생성하고, 여러분의 모델에 대해 호출을 실행하고, 스토리지를 사용하고, 또는 제3자에게 지급을 발생시켰다면, 그 비용들은 실제 돈으로 지불되었고 환불로 돌아오지 않습니다. 알림은 그 어느 것도 회수할 수 없습니다. 알림이 할 수 있는 것은 여기서부터의 출혈을 멈추는 것이며, 그것이 바로 빠르게 대응해야 할 전적인 이유입니다.
출혈이 가장 심한 것은 구독과 차지백입니다. 취소하지 못한 구독은 더 이상 지불하지 않는 고객을 위해 달마다 계속해서 서비스 비용을 발생시킵니다. 그리고 차지백은 가장 비싼 종류의 무효화입니다. 2026년 8월 3일부터 Google의 문서는 차지백이 구매 가격에 은행 수수료를 더한 금액을 개발자에게 전가한다고 명시합니다. 무효화된 구매 알림은 차지백이 완료되었다는 것을 여러분 자신의 시스템이 처음 듣는 곳인 경우가 많으므로, 즉석에서 취소하는 핸들러가 잃어버린 판매를 잃어버린 판매에 몇 주간의 무료 서비스를 더한 것으로 바뀌지 않게 지켜 줍니다.
무효화된 구매 알림을 처리하는 방법, 단계별로
메시지를 검증하고 중복을 제거한다
- Pub/Sub 메시지가 Google에서 왔고 여러분이 구성한 토픽을 대상으로 하는지 확인한 다음, base64
data필드를 디코딩하여DeveloperNotificationJSON을 얻습니다. - Pub/Sub
messageId를 사용하여 중복을 버립니다. Google은 동일한 알림이 두 번 이상 전달될 수 있다고 경고하므로, 재전송을 정상으로 취급하고 핸들러를 멱등하게 만드십시오. - 메시지를 안전하게 기록한 후에만 확인 응답하십시오. 그래야 핸들러 도중의 크래시로 이벤트를 잃지 않습니다.
구매를 조회한다
purchaseToken을 처음 이용 권한을 부여했을 때 저장한 구매와 대조합니다. 지원 조회와 수동 대조에는orderId를 대체 수단으로 사용합니다.productType을 읽어 구독 또는 일회성 취소 경로를 선택하고,refundType을 읽어 전액 취소와 부분 취소 중 무엇을 할지 결정합니다.
취소하고 기록한다
- 이용 권한을 제거합니다. 전액 환불의 경우, 해당 항목에 대한 접근을 차단합니다. 수량 기반 부분 환불의 경우, 부여한 수량을 환불된 만큼 줄이고 나머지는 그대로 둡니다.
- 무엇을 언제 했는지
purchaseToken과orderId를 키로 삼아 기록합니다. 그 기록이 나중에 지원 티켓에 답할 수 있게 해 주고, Voided Purchases API가 여러분 자신의 상태에 대해 깔끔하게 대조할 수 있게 해 줍니다.
그것이 다른 환불 신호들 사이에서 어디에 위치하는가
무효화된 구매 알림은 통지이지 협상이 아닙니다. 그것은 이미 결정된 결과를 알려 줍니다. 혼동하기 쉬운 신호들과 나란히 두고 보는 것이 가치가 있습니다. 왜냐하면 그중 일부만이 여러분 쪽의 이야기를 요청하기 때문입니다.
| 신호 | 방향 | 여러분의 입력을 받는가 |
|---|---|---|
| 무효화된 구매 알림 (RTDN) | Google이 서버로 푸시 | 아니요. 이미 발생한 무효화를 보고한다 |
| Voided Purchases API | 서버가 Google에서 풀 | 아니요. 과거 무효화의 읽기 전용 목록이다 |
pendingRefundReviewNotification (RTDN) | Google이 서버로 푸시 | 예, 간접적으로. 차지백을 표시하며, 여러분은 24시간 이내에 orders.reviewrefund를 통해 이의를 제기한다 |
| Apple CONSUMPTION_REQUEST | Apple이 서버에 요청 | 예. 12시간 이내에 Send Consumption Information으로 응답한다 |
붙잡아야 할 요점은 단순합니다. 두 스토어를 통틀어 개발자가 발언권을 갖는 환불 흐름은 정확히 두 가지, Apple의 CONSUMPTION_REQUEST와 Google Play의 차지백 검토뿐입니다. 무효화된 구매 알림은 그 어느 것도 아닙니다. 그것이 여러분에게 도달할 무렵에는 결정은 이미 지나간 일이고, 여러분의 손에 남은 유일한 것은 얼마나 빨리 취소하느냐뿐입니다.
자주 묻는 질문
- Google Play에서 무효화된 구매 알림은 무엇을 의미하나요?
- 그것은 구매가 환불, 차지백, 또는 그 밖의 방식으로 무효화되었고 고객이 환불을 받았다는 것을 의미합니다. Google의 안내는 구매자가 더 이상 이용 권한을 보유해서는 안 되므로 관련 콘텐츠에 대한 접근 권한을 취소하라는 것입니다. 알림은 `purchaseToken`과 `orderId`를 통해 정확한 구매를 지목합니다.
- Google Play 무효화된 구매 알림에는 어떤 필드가 들어 있나요?
- 네 가지입니다. `purchaseToken`, `orderId`, `productType`, `refundType`. `productType`는 구독일 때 `1`, 일회성 구매일 때 `2`입니다. `refundType`는 전액 환불일 때 `1`, 다중 수량 구매의 수량 기반 부분 환불일 때 `2`입니다.
- 무효화된 구매 알림은 어떻게 활성화하나요?
- Play Console에서 Monetize 그다음 Monetization setup을 열고, Real-time developer notifications 섹션에서 Enable real-time notifications를 체크한 다음, Cloud Pub/Sub 토픽 이름을 입력합니다. 콘텐츠 옵션 두 가지, 즉 구독과 모든 무효화된 구매, 그리고 여기에 일회성 제품 이벤트를 더한 것 모두 무효화된 구매를 포함합니다.
- 무효화된 구매 알림과 Voided Purchases API의 차이는 무엇인가요?
- 알림은 구매가 무효화되는 순간 Cloud Pub/Sub를 통해 실시간으로 전달되는 푸시 신호입니다. Voided Purchases API는 특정 기간의 무효화를 나열하기 위해 서버가 자체 일정에 따라 조회하는 풀 방식입니다. 즉시 대응하려면 알림을, 대조와 메우기에는 API를 사용하십시오.
- 무효화된 구매 알림으로 환불에 이의를 제기할 수 있나요?
- 아니요. 그것은 이미 내려진 결정의 사후 통지입니다. 여러분의 입력을 받는 유일한 Google Play 흐름은 `orders.reviewrefund`를 통한 차지백 검토이며 답변 기한은 24시간이고, Apple에서는 12시간 기한이 있는 CONSUMPTION_REQUEST가 그에 해당합니다.
출처 및 추가 자료
- Android Developers: Real-time developer notifications reference guide
- Google Play Developer API: Voided Purchases API
- Google Play Developer API: REST Resource purchases.voidedpurchases
- Android Developers: Purchase lifecycle and RTDNs
- Google Play Console Help: refund protection and chargeback cost responsibility
- Google Play Developer API: Method orders.reviewrefund
RefundHalt
App Store와 Google Play 환불 자동 처리
계속 읽기
Google Play 주문은 직접 환불할 수 있으며, 지불 거절이 되기 전에 처리하면 은행 수수료를 아낄 수 있습니다
3년 이내의 Google Play 주문이라면 어느 것이든 API 호출 한 번으로 환불할 수 있으며, 그때 접근 권한을 취소할지 여부도 선택할 수 있습니다. 분쟁이 지불 거절로 번지기 전에 직접 환불하면 2026년 8월 3일부터 개발자에게 부과되는 은행 수수료를 아낄 수 있습니다. 아래에서 orders.refund 사용법을 설명합니다.
Apple의 Send Consumption Information이 이제 열두 개가 아니라 다섯 개의 필드를 요구합니다. 아래에서 하나씩 살펴봅니다
고객이 Apple에 환불을 요청할 때 Send Consumption Information 페이로드가 여러분의 답변입니다. Apple은 이를 열두 개 필드에서 다섯 개로, 필수 세 개와 선택 두 개로 줄였습니다. 아래에서 각 필드, 각각이 받아들이는 값, 그리고 이를 보내야 하는 12시간의 창을 설명합니다.