GET 메서드를 사용하여 무효화된 구매 목록을 요청합니다. 요청에 앱의 정규화된 패키지 이름(예: com.google.android.apps.maps)과 API에 대한 액세스 권한을 얻을 때 받은 승인 토큰을 포함합니다.
GET https://www.googleapis.com/androidpublisher/v3/applications/
your_package_name/purchases/voidedpurchases?access_token=your_auth_token
다음과 같은 매개변수를 요청에 포함할 수도 있습니다(선택사항).
startTime
응답에 표시하려는 무효화된 구매 중 가장 오래된 구매의 시간(유닉스 시간 이후, 밀리초 단위)입니다. 기본적으로 startTime은 30일 전으로 설정됩니다.
Voided Purchases API는 지난 30일 동안의 무효화된 구매만 표시합니다. 무효화된 구매 중 더 오래된 구매는 startTime에 제공한 값과 상관없이 응답에 포함되지 않습니다.
endTime
응답에 표시하려는 무효화된 구매 중 가장 최근 구매의 시간(유닉스 시간 이후, 밀리초 단위)입니다. 기본적으로 endTime은 현재 시간으로 설정됩니다.
maxResults
각 응답에 표시되는 무효화된 구매의 최대 수입니다. 기본적으로
이 값은 1,000입니다. 이 매개변수의 최댓값도 1,000입니다.
token
이전 응답의 연속 토큰이며, 이를 통해 더 많은 결과를 볼 수 있습니다.
type
각 응답에 표시되는 무효화된 구매의 유형입니다. 0으로 설정하면 무효화된 인앱 구매만 반환됩니다. 1로 설정하면 무효화된 인앱 구매와 무효화된 정기 결제 구매가 모두 반환됩니다. 기본값은 0입니다.
includeQuantityBasedPartialRefund
수량 기반의 부분 환불 중 무효화된 구매가 포함되었는지 여부를 나타내며, 이는 다중 수량 구매에만 적용됩니다. true인 경우, 수량 기반의 부분 환불 중 환불된 수량을 나타내는 voidedQuantity를 사용해 무효화된 구매를 추가로 반환할 수 있습니다. 기본값은 false입니다.
응답은 무효화된 구매 목록이 포함된 JSON 문자열입니다. 결과 개수가 maxResults 요청 매개변수에 지정된 수보다 많으면 응답에 nextPageToken 값이 포함됩니다. 이 값을 후속 요청에 전달하면 더 많은 결과를 볼 수 있습니다. 목록의 첫 번째 결과에는 무효화된 구매 중 가장 오래된 구매가 표시됩니다.
초기 API 요청 중에 앱에 사용할 수 있는 모든 데이터를 가져오는 것이 좋습니다. 드물지만 이 과정에서 일일 할당량이 소진될 수 있습니다. 무효화된 구매 데이터를 더 안전하고 일관된 방식으로 가져오려면 다음 권장사항을 따르세요.
maxResults 매개변수에 기본값을 사용합니다. 이렇게 하면 일일 쿼리 할당량을 모두 사용하여 무효화된 구매 600만 개에 관한 세부정보를 검색할 수 있습니다.
응답에 nextPageToken 값이 포함된 경우 다음 요청 중에 이 값을 token 매개변수에 할당합니다.
권장사항
앱에서 이 API를 사용할 때는 구매를 무효화하는 이유는 다양하며 모든 사례에 맞는 단 하나의 솔루션은 없다는 사실에 유의하세요. 취소 정책과 전략을 설계할 때 사용자를 염두에
두세요. 전략을 설계할 때 다음과 같은 권장 사용 방법을 적용할 수 있습니다.
원치 않는 동작을 처리하기 위한 포괄적인 전략에서 다양한 요소 중 하나로써
이 API를 사용합니다. 인앱 제품 액세스 권한을 취소하는 것은 인앱 구매 가격이
합리적인 앱, 바람직하지 않은 동작을 권장하지 않는 앱 설계, 바람직하지 않은 동작을
거부하는 문화를 가진 강력한 사용자층, 반응이 빠르고 효율적인 사용자 지원 채널 등과
같은 조건에서 더 효과적입니다.
모든 사용자에게 공정하게 적용되도록 취소 정책을 균일하게 관리합니다.
원치 않는 동작을 처리할 때 단계별 정책을 작성하는 것이 좋습니다. 예를 들어,
초기 위반 사항에는 인앱 경고로 대응한 다음 사용자의 원치 않는 행동이
지속되면 대응의 수준을 점점 높입니다. 최후의 수단으로 사용자가 앱과
상호작용하지 못하도록 차단할 수도 있습니다.
취소 정책을 도입한 후 정책을 업데이트할 때마다 앱의 대응 채널을 통해
변경 사항을 사용자에게 알립니다. 변경 사항을 앱에 적용하기 전에 사용자가
변경 사항을 명확하게 이해할 수 있는 시간을 제공합니다.
인앱 제품에 관한 액세스 권한 취소 등과 같은 조치를 할 때마다
사용자에게 투명하게 알립니다. 사용자가 결정에 이의를 제기할 수 있어야 하며
이의 사항은 공정하게 처리해야 합니다.
의견 양식과 커뮤니티 포럼을 모니터링하여 사용자가 바람직하지 않은 행동을
보이는 이유와 행동 방식을 파악합니다. 이러한 정보를 1차 방어선으로 활용하세요.
[null,null,["최종 업데이트: 2025-08-18(UTC)"],[[["\u003cp\u003eThe Google Play Voided Purchases API lets you track voided in-app purchases and subscriptions to implement revocation systems, ensuring a fair user experience.\u003c/p\u003e\n"],["\u003cp\u003eVoided purchases include user refunds, cancellations, chargebacks, and cancellations/refunds by the developer or Google.\u003c/p\u003e\n"],["\u003cp\u003eAccess the API using OAuth or a service account with "View financial reports" permission and make requests with your package name and authorization token.\u003c/p\u003e\n"],["\u003cp\u003eTailor your revocation policies to be fair and transparent, escalating responses as needed while informing users of any actions taken.\u003c/p\u003e\n"],["\u003cp\u003eCombine this API with other strategies and real-time notifications for a comprehensive approach to managing user entitlements and addressing undesirable behaviors.\u003c/p\u003e\n"]]],["The Google Play Voided Purchases API lists orders linked to user-voided purchases, including refunds, cancellations, chargebacks, and developer/Google-initiated voids. This API helps developers implement revocation systems to prevent access to products from voided orders. To use it, developers need \"View financial reports\" permission and can use a `GET` method to request voided purchases, filtering by time, quantity, or type. It has quotas, provides best practices and advises using it along side RTDN.\n"],null,["# Voided Purchases API\n\nThe Google Play Voided Purchases API provides a list of orders that\nare associated with purchases that a user has voided. You can use information\nfrom this list to implement a revocation system that prevents the user from\naccessing products from those orders.\n\nThis API applies to one-time in-app orders and App Subscriptions.\n\nA purchase can be voided in the following ways:\n\n- The user requests a refund for their order.\n- The user cancels their order.\n- An order is charged back.\n- Developer cancels or refunds order.\n\n | **Note:** only revoked orders will be shown in the Voided Purchases API. If a developer refunds a purchase without setting the revoke option, the order will not be returned by the API.\n- Google cancels or refunds order.\n\nBy using this API, you help create a more balanced and fair experience for all\nof your app's users, particularly if your app is a game.\n| **Note:** Unlike other order-related data sources, the Voided Purchases API includes purchases that are charged back by payment processors. Therefore, you might see inconsistencies between the information from this API and information from other order-related data sources.\n| **Note:** The Voided Purchases API returns voided purchases only when they need to be revoked. Developers can use this API as an indication for when to take additional action on their end. However, some purchases may be refunded with reason that the purchase was never acknowledged by the developer, and therefore may not exist in the developer's records.\n\nGaining Access\n--------------\n\nTo work with the Voided Purchases API, you need to have permission to view\nfinancial information. You provide authorization using an OAuth client or a\nservice account. If you're using a service account, enable the \"View financial\nreports\" permission within this account.\n\nTo learn more about gaining authorized access to Google Play Developer APIs, see\nthe following guides:\n\n- [Setting Up API Access Clients](/android-publisher/getting_started#setting_up_api_access_clients)\n- [Add developer account users \\& manage permissions](https://support.google.com/googleplay/android-developer/answer/2528691)\n\nViewing Voided Purchases\n------------------------\n\nUse the `GET` method to request a list of voided purchases. In your request,\ninclude the fully-qualified package name for your app---such as\n`com.google.android.apps.maps`---and the authorization token you\nreceived when [gaining access](#gaining_access) to the API. \n\n```\nGET https://www.googleapis.com/androidpublisher/v3/applications/\nyour_package_name/purchases/voidedpurchases?access_token=your_auth_token\n```\n\nYou can also include the following parameters in your request, each of which is\noptional:\n\nstartTime\n\n: The time, in milliseconds since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time), of the oldest\n voided purchase that you want to see in the response. By default,\n `startTime` is set to 30 days ago.\n\n The API can only show voided purchases that have occurred during the past\n 30 days. Older voided purchases are not included in the response, regardless\n of the value that you've provided for `startTime`.\n | **Note:** The voided purchases within the response are filtered based on the time at which a given record is seen as voided by the API, not by the value of `voidedTimeMillis` returned in the response.\n\nendTime\n\n: The time, in milliseconds since the [Unix epoch](https://en.wikipedia.org/wiki/Unix_time), of the newest\n voided purchase of that you want to see in the response. By default,\n `endTime` is set to the current time.\n\n | **Note:** The voided purchases within the response are filtered based on the time at which a given record is seen as voided by the API, not by the value of `voidedTimeMillis` returned in the response.\n\nmaxResults\n: The maximum number of voided purchases that appear in each response. By\n default, this value is 1000. Note that the maximum value for this parameter is\n also 1000.\n\ntoken\n: A continuation token from a previous response, allowing you to view more\n results.\n\ntype\n\n: The type of voided purchases that appear in each response. If set to 0,\n only voided in-app purchases will be returned. If set to 1, both voided in-app\n purchases and voided subscription purchases will be returned. Default value is\n 0.\n\n | **Note:** Before requesting to receive voided subscription purchases, you must switch to use orderId in the response which uniquely identifies one-time purchases and subscriptions. Otherwise, you will receive multiple subscription orders with the same PurchaseToken.\n\nincludeQuantityBasedPartialRefund\n\n: Whether to include voided purchases of quantity-based partial refunds,\n which are applicable only to multi-quantity purchases. If `true`,\n additional voided purchases may be returned with `voidedQuantity`\n that indicates the refund quantity of a quantity-based partial refund. The\n default value is `false`.\n\n | **Note:** When the remaining total quantity of a purchase is refunded, the corresponding voided purchase won't have `voidedQuantity`, which serves as a signal that the purchase has been fully refunded. For example, if a purchase of quantity 10 is refunded 3 times with quantities 2, 3 and 5, there will be 3 voided purchases. The first two voided purchases will have a `voidedQuantity` of 2 and 3, while the third voided purchase *will not* have a `voidedQuantity`.\n\nThe response is a JSON string that contains a list of voided purchases. If there\nare more results than the number specified in the `maxResults` request parameter\n, the response includes a `nextPageToken` value, which you can pass into a\nsubsequent request to view more results. The first result in the list shows the\noldest voided purchase. \n\n```\n{\n \"tokenPagination\": {\n \"nextPageToken\": \"next_page_token\"\n },\n \"voidedPurchases\": [\n {\n \"kind\": \"androidpublisher#voidedPurchase\",\n \"purchaseToken\": \"some_purchase_token\",\n \"purchaseTimeMillis\": \"1468825200000\",\n \"voidedTimeMillis\": \"1469430000000\",\n \"orderId\": \"some_order_id\",\n \"voidedSource\": \"0\",\n \"voidedReason\": \"4\"\n },\n {\n \"kind\": \"androidpublisher#voidedPurchase\",\n \"purchaseToken\": \"some_other_purchase_token\",\n \"purchaseTimeMillis\": \"1468825100000\",\n \"voidedTimeMillis\": \"1470034800000\",\n \"orderId\": \"some_other_order_id\",\n \"voidedSource\": \"2\",\n \"voidedReason\": \"5\"\n },\n ]\n}\n```\n\nQuotas\n------\n\nThe Voided Purchases API sets the following quotas on a per-package basis:\n\n- 6000 queries per day. (The day begins and ends at midnight Pacific Time.)\n- 30 queries during any 30-second period.\n\n### Guidelines for initial requests\n\nDuring your initial API request, you may want to fetch all available data for\nyour app. Although unlikely, this process could exhaust your daily quota. To\nobtain voided purchases data in a safer, more consistent manner, follow these\nbest practices:\n\n- Use the default value for the `maxResults` parameter. That way, if you use your entire query quota for a day, you can retrieve the details of 6,000,000 voided purchases.\n- If a response includes a value for `nextPageToken`, assign this value to the `token` parameter during your next request.\n\nBest Practices\n--------------\n\n| **Note:** In addition to using this API, developers should integrate with [Real-time developer notifications (RTDN)](https://developer.android.com/google/play/billing/getting-ready#configure-rtdn). With RTDN, you receive notifications from Google whenever there is a change in a user's entitlement within your app, including when a user [voids a purchase](https://developer.android.com/google/play/billing/rtdn-reference#voided-purchase).\n\nWhen using this API in your app, remember that there are many\nreasons to void a purchase and that there is no single solution that works in\nall cases. You should keep your users in mind when designing your revocation\npolicies and strategies. To do so, you can apply these recommended practices:\n\n- Use this API as one of many elements in a comprehensive strategy to address undesired behavior. Revoking access to in-app products is usually more effective when combined with an app that has reasonable prices for in-app purchases, an app design that discourages undesirable behavior, a strong user base whose culture rejects such behavior, and responsive and efficient user support channels.\n- Administer your revocation policy uniformly to ensure fairness for all users.\n- Consider creating a staged policy when addressing undesired behavior. For example, start with in-app warnings for early offenses, then escalate your responses as a user's undesired behavior continues. As a last resort, you can prevent a user from interacting with your app at all.\n- When you introduce a revocation policy, and each time you update it, use your app's outreach channels to inform your users about the changes. Give your users time to clearly understand these changes before they take effect in your app.\n- Be transparent to your users and inform them whenever you take action, such as revoking their access to an in-app product. Ideally, users should be able to dispute your decisions, and such disputes should be treated fairly.\n- Monitor feedback forms and community forums to understand what drives users to behave in undesirable ways and how they carry out such behavior. Act on these insights as a first line of defense."]]