Reminder: By Aug 31, 2025, all new apps and updates to existing apps must use Billing Library version 7 or newer. If you need more time to update your app, you can request an extension until Nov 1, 2025. Learn about Play Billing Library version deprecation.
구매가 합법적이며 과거에 사용되지 않았다면 인앱 상품 또는 정기 결제에 안전하게 자격을 부여할 수 있습니다.
또한, 정기 결제의 경우 Purchases.subscriptionsv2:get에 linkedPurchaseToken이 설정될 때 데이터베이스에서 linkedPurchaseToken을 삭제하고 linkedPurchaseToken에 부여된 자격을 취소하여 여러 사용자에게 동일한 구매 자격이 부여되지 않도록 해야 합니다.
구매 상태가 PURCHASED인 경우에만 자격을 부여해야 하며 PENDING 구매를 올바르게 처리해야 합니다. CANCELED 상태가 급증하고 있다면 구매가 아직 PENDING 상태더라도 자격을 부여할 수 있습니다. 자세한 내용은 대기 중인 거래 처리를 참고하세요.
앱을 통해 클라이언트 측에서 구매를 확인하거나 소비할 수 있지만 서버 측 API는 네트워크 연결 불량, 악의적인 활동과 같은 문제를 방지하기 위해 추가적인 보호 기능을 제공합니다. 예를 들어 사용자가 앱에서 상품을 구매했지만 구매 검증 과정에서 네트워크 연결이 끊겼다고 가정해 보겠습니다. 서버 확인이 없으면 앱을 통해 다시 로그인하여 확인 절차를 완료해야 할 수 있습니다. 그러지 않는 경우 사용자가 3일 이내에 다시 로그인하지 않으면 구매 확인 부족으로 인해 구매가 자동으로 환불됩니다. 서버 확인은 Google Play에서 서버에 구매가 유효함을 알리는 즉시 확인을 전송하여 이러한 시나리오를 방지합니다.
악의적인 사용자가 잠금 해제된 콘텐츠를 재배포하는 것을 방지하려면 콘텐츠를 APK 파일에 번들로 포함하지 마시기 바랍니다. 그 대신, 다음 방법 중 하나를 따르세요.
실시간 서비스를 사용하여 콘텐츠 피드와 같은 콘텐츠를 제공합니다.
또한, 실시간 서비스를 통해 콘텐츠를 제공하면 콘텐츠를 최신 상태로 유지할 수 있습니다.
원격 서버를 사용하여 콘텐츠를 제공합니다.
원격 서버나 실시간 서비스를 통해 콘텐츠를 제공하면 잠금 해제된 콘텐츠를 기기 메모리나 기기의 SD 카드에 저장할 수 있습니다.
SD 카드에 콘텐츠를 저장하는 경우 콘텐츠를 암호화하고 기기별 암호화 키를 사용해야 합니다.
무효화된 구매 감지 및 처리
무효화된 구매는 취소되거나 지불이 거절된 구매입니다. 무효화된 구매에서 이전에 인앱 상품이나 기타 콘텐츠를 사용자에게 부여했다면 Voided Purchases API를 사용하여 회수할 수 있는 연결된 콘텐츠와 함께 구매가 무효화된 이유를 확인할 수 있습니다.
인앱 상품 및 정기 결제 구매는 다음과 같은 여러 이유로 무효화될 수 있습니다.
사용자, 개발자 또는 Google에서 구매를 취소한 경우(미확인 자동 취소 구매 포함).
정기 결제의 경우 정기 결제 자체를 취소하는 것이 아니라 정기 결제의 구매를 취소하는 것입니다.
구매가 지불 거절된 경우
앱 개발자가 사용자 주문을 취소하거나 환불하고 콘솔에서 '취소' 옵션을 선택한 경우
무효화된 구매의 이유 및 사용자의 이전 행동 데이터를 고려하여 어떻게 조치할지 결정할 수 있습니다. 다음 중 하나 이상을 구현하는 것이 좋습니다.
회수 실행: 구매가 무효화되면 구매한 적이 없는 것처럼 미사용 상품을 회수할 수 있습니다. 예를 들어, 인게임 화폐 구매가 무효화되면 사용자에게 이미 부여된 화폐를 회수할 수 있습니다. 사용자가 이미 화폐를 사용한 경우에는 화폐 잔액을 마이너스로 설정하고 화폐 잔액이 마이너스를 벗어날 때까지 앱 활동 및 향후 구매를 제한하는 것이 좋습니다.
여러 차례 위반에 관한 구현: 인앱 경고 표시와 같이 최초 위반자에게는 덜 강경한 조치를 취하는 것이 좋습니다. 반복적인 위반자의 경우 더 심각한 조치를 고려합니다.
일시적 구매 중지: 여러 차례 위반에 관한 구현과 마찬가지로 구매가 무효화된 이유를 더 철저하게 조사할 수 있을 때까지 구매를 무효화한 사용자의 구매를 중지하는 것이 좋습니다.
일시적 또는 영구적으로 앱 액세스 차단: 반복적이고 악의적인 활동을 하는 극단적인 경우에는 일시적 또는 영구적으로 앱 액세스를 차단하는 것이 좋습니다.
Voided Purchases API의 빈번한 호출: 하나 이상의 무효화된 구매를 감지했다면 Voided Purchases API를 더 자주 호출하여 사용자가 구매를 소비하기 전에 회수하는 것이 좋습니다. Voided Purchases API 문서에서 Voided Purchases API 할당량에 관한 자세한 내용을 확인할 수 있습니다.
사기가 발생하기 전에 Google이 감지하도록 돕기
일부 사기 유형은 여러 개의 Google 및 인앱 계정을 만들어서 활동을 숨기는 악의적인 사용자와 관련이 있습니다.
Google은 이 데이터를 사용하여 의심스러운 행동을 감지하고 거래가 완료되기 전에 일부 유형의 사기 거래를 차단합니다.
상표권 및 저작권 침해에 관한 조치
원격 서버를 사용하여 콘텐츠를 전송 또는 관리하고 있다면 사용자가 콘텐츠에 액세스할 때마다 앱에서 잠금 해제된 콘텐츠의 구매 상태를 확인하도록 합니다. 이렇게 하면, 필요할 때 사용을 취소하고 불법 복제를 최소화할 수 있습니다.
자신의 콘텐츠가 Google Play에서 재배포되는 것을 발견했다면 신속하고 단호하게 조치를 취해야 합니다. 자세한 내용은 저작권 고객센터의 저작권 FAQ 페이지를 참조하세요.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[null,null,["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Fight fraud and abuse\n\nAs your app grows in popularity, it can also attract the unwanted\nattention of malicious users that might want to abuse your app. This topic\ndescribes recommendations that you should use to help prevent these attacks on\nyour billing integration and decrease the impact of abuse in your app.\n\nMove sensitive logic to your backend\n------------------------------------\n\nAs much as your app design permits, move sensitive data and logic to a backend\nserver that you control. The more data and logic you have in a frontend device,\nthe more vulnerable it is to being modified or tampered with.\n\nFor example, an online chess game should validate all moves in the backend\ninstead of trusting that the frontend always sends legal moves.\n\nFurthermore, if you find vulnerabilities or security issues, depending on your system design, it might be easier to debug, fix, and roll out updates on the\nbackend rather than the frontend.\n\nVerify purchases before granting entitlements\n---------------------------------------------\n\nA special case of sensitive data and logic that should be handled in the backend\nis purchase verification and acknowledgement. After a user has made a purchase,\nyou should do the following:\n\n1. Send the corresponding `purchaseToken` to your backend. This means that you should maintain a record of all `purchaseToken` values for all purchases.\n2. Verify that the `purchaseToken` value for the current purchase does not match any previous `purchaseToken` values. `purchaseToken` is globally unique, so you can safely use this value as a primary key in your database.\n3. Use the [`Purchases.products:get`](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/get) or [`Purchases.subscriptionsv2:get`](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptionsv2/get) endpoints in the Google Play Developer API to verify with Google that the purchase is legitimate.\n4. If the purchase is legitimate and has not been used in the past, you can then safely grant entitlement to the in-app item or subscription.\n5. For subscriptions, when [`linkedPurchaseToken`](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptionsv2) is set in `Purchases.subscriptionsv2:get`, you should also remove the `linkedPurchaseToken` from your database and revoke the entitlement that is granted to the `linkedPurchaseToken` to ensure that multiple users are not entitled for the same purchase.\n6. You should grant entitlement only when the purchase state is `PURCHASED` and make sure to handle the `PENDING` purchases correctly. If there is a spike of `CANCELED` purchases, you may be granting entitlements when the purchase is still in `PENDING` state. You can find more information at [Handling pending transactions](/google/play/billing/integrate#pending).\n7. After granting entitlement, if you want to consume and acknowledge a\n consumable product, use the\n [`Purchases.products:consume`](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/consume)\n Play Developer API on your secure backend server.\n To acknowledge a non-consumable product or a subscription,\n call the relevant Play Developer API endpoint, either\n [`Purchases.products:acknowledge`](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/acknowledge)\n or\n [`Purchases.subscriptions:acknowledge`](https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.subscriptions/acknowledge)\n on your secure backend server.\n Acknowledgment is required, as it notifies Google Play that the user has\n been granted entitlement to the purchase. You should acknowledge the\n purchase immediately after granting entitlement.\n\n Note that while you can acknowledge or consume the purchase on the client\n side through your app, server side APIs provide additional protection\n against issues like poor network connectivity and malicious activity. For\n example, consider if a user has purchased an item from your app but they\n lost network connectivity while the purchase was being validated. Without\n server acknowledgment, they might need to log back in through the app to\n complete the acknowledgement process. Otherwise, if the user does not log\n back in within three days, the purchase is automatically refunded due to\n lack of purchase acknowledgement. Server acknowledgment prevents this\n scenario by sending acknowledgment as soon as Google Play notifies the\n server that the purchase is valid.\n\n For more information about purchase acknowledgment and consumption, see\n [Processing purchases](https://developer.android.com/google/play/billing/integrate#process).\n\n| **Note:** Do not grant entitlement when the purchase state is `PENDING`.\n| **Note:** Do not use `orderId` to check for duplicate purchases or as a primary key in your database, as not all purchases are guaranteed to generate an `orderId`. In particular, purchases made with promo codes do not generate an `orderId`.\n\nProtecting your unlocked content\n--------------------------------\n\nTo prevent malicious users from redistributing your unlocked content, do not\nbundle it in your APK file. Instead, do one of the following:\n\n- Use a real-time service to deliver your content, such as a content feed. Delivering content through a real-time service also enables you to keep your content fresh.\n- Use a remote server to deliver your content.\n\nWhen you deliver content from a remote server or a real-time service, you can\nstore the unlocked content in device memory or store it on the device's SD card.\nIf you store content on an SD card, be sure to encrypt the content and use a\ndevice-specific encryption key.\n\nDetect and handle voided purchases\n----------------------------------\n\n*Voided purchases* are purchases that have been canceled, revoked, or\ncharged back. If a voided purchase had previously granted in-app items or other\ncontent to a user, you can use the\n[Voided Purchases API](https://developers.google.com/android-publisher/voided-purchases)\nto obtain the reason the purchase was voided along with any associated\ncontent that you can claw back.\n| **Note:** Voided purchases without any associated clawback content are not exposed by the Voided Purchases API.\n\nPurchases for in-app items and subscriptions can be voided for a variety of\nreasons, including the following:\n\n- A purchase is canceled, either by the user, by the developer, or by Google (including unacknowledged auto-canceled purchases). For subscriptions, note that this refers to canceling the *purchase* of a subscription, rather than [canceling the subscription itself](https://support.google.com/googleplay/answer/7018481?co=GENIE.Platform%3DAndroid).\n- A purchase is charged back.\n- The app developer cancels or refunds a user order and checks the \"revoke\" option in the console.\n\nBased on the reason for the voided purchase, and taking previous user\nbehavioral data into account, you can decide on a course of action. We recommend\nimplementing one or more of the following:\n\n- **Perform clawbacks:** When a purchase is voided, you can claw back unused items as if they were never purchased. For example, if an in-game currency purchase was voided, you could claw back currency that was already granted to the user. In the case where the user has already spent the currency, consider setting the currency balance to negative and limiting app activity and future purchases until the currency balance is positive.\n- **Multiple strikes implementation:** Consider taking less drastic actions for first-time offenders, such as displaying in-app warnings. For repeat offenders, consider more severe measures.\n- **Temporarily disable purchases:** Similar to the multiple strikes implementation, consider disabling purchases for users with voided purchases until you can more thoroughly investigate why the purchases were voided.\n- **Temporarily or permanently disallow access to your app:** For extreme cases with repeated malicious activity, consider disallowing access to your app, either temporarily or permanently.\n- **Make frequent calls to the Voided Purchases API:** When you detect one or more voided purchases, consider making more frequent calls to the Voided Purchases API to claw back purchases before the user can consume them. You can find more information on Voided Purchases API quotas in the [Voided Purchases API documentation](https://developers.google.com/android-publisher/voided-purchases#quotas).\n\nHelp Google detect fraud before it happens\n------------------------------------------\n\nSome types of fraud are related to malicious users who create multiple Google\nand in-app accounts to hide their activity.\n\nUse the\n[`setObfuscatedAccountId`](/reference/com/android/billingclient/api/BillingFlowParams.Builder#setObfuscatedAccountId(java.lang.String))\nand\n[`setObfuscatedProfileId`](/reference/com/android/billingclient/api/BillingFlowParams.Builder#setobfuscatedprofileid)\nmethods in the builder for\n[`BillingFlowParams`](/reference/com/android/billingclient/api/BillingFlowParams.Builder)\nto help Google map Google Accounts to in-app accounts.\n\nGoogle uses this data to detect suspicious behavior and block some types of fraudulent transactions before they are completed.\n\nTaking action against trademark and copyright infringement\n----------------------------------------------------------\n\nIf you are using a remote server to deliver or manage content, have your\napp verify the purchase state of the unlocked content whenever a user accesses\nthe content. This allows you to revoke use when necessary and minimize piracy.\nIf you see your content being redistributed on Google Play, be sure to act\nquickly and decisively. For more details, see the\n[Frequently Asked Copyright Questions](https://support.google.com/legal/answer/4558836)\npage in the Copyright Help Center."]]