이 주제에서는 갱신 및 만료와 같은 정기 결제 수명 주기 이벤트를 처리하는 방법을 설명합니다. 또한 프로모션을 제공하고 사용자가 자신의 정기 결제를 관리하도록 허용하는 등의 추가 정기 결제 기능도 설명합니다.
앱의 정기 결제 제품을 구성하지 않았다면 제품 생성 및 구성을 참고하세요.
정기 결제 개요
정기 결제는 지정된 기간 동안 사용자가 액세스할 수 있는 일련의 혜택을 나타냅니다. 예를 들어 정기 결제로 사용자는 음악 스트리밍 서비스에 액세스할 수 있습니다.
동일한 앱 내에서 다양한 혜택 또는 한 가지 혜택의 다양한 등급(예: '실버' 등급, '골드' 등급)을 나타내는 여러 개의 정기 결제를 만들 수 있습니다.
기본 요금제와 혜택을 통해 동일한 정기 결제 제품의 여러 구성을 만들 수 있습니다. 예를 들어 앱을 정기 결제한 적이 없는 사용자를 위한 신규 할인 혜택을 만들 수 있습니다. 마찬가지로 이미 정기 결제 중인 사용자를 위한 업그레이드 혜택을 만들 수도 있습니다.
정기 결제 제품, 기본 요금제, 혜택에 관한 자세한 내용은 Play Console 고객센터의 문서를 참고하세요.
선불 요금제 통합
선불 요금제는 만료 시 자동으로 갱신되지 않습니다. 서비스 중단 없이 정기 결제 사용 권한을 연장하려면 사용자가 동일한 정기 결제의 선불 요금제를 충전해야 합니다.
충전의 경우 원래 구매에서와 마찬가지로 결제 흐름을 시작합니다. 구매가 충전이라고 표시할 필요는 없습니다.
선불 요금제 충전은 항상 IMMEDIATE_AND_CHARGE_FULL_PRICE
비례 배분 모드를 사용하므로 이 모드를 명시적으로 설정하지 않아도 됩니다.
사용자에게 전체 결제 기간이 즉시 청구되며 충전에 지정된 기간까지 사용 권한이 연장됩니다.
충전이 완료되면 Purchase
결과 객체의 다음 필드가 최근에 충전된 구매를 반영하도록 업데이트됩니다.
- 주문 ID
- 구매 시간
- 서명
- 구매 토큰
- 확인됨
다음 Purchase
필드에는 항상 원래 구매에 있는 것과 동일한 데이터가 포함됩니다.
- 패키지 이름
- 구매 상태
- 제품
- 자동 갱신
선불 구매 확인
자동 갱신 정기 결제와 마찬가지로 구매 후에는 선불 요금제를 확인해야 합니다. 최초 구매와 충전을 모두 확인해야 합니다. 자세한 내용은 구매 처리를 참고하세요.
선불 요금제의 기간이 짧을 수 있으므로 가능한 한 빨리 구매를 확인하는 것이 중요합니다.
기간이 1주 이상인 선불 요금제는 3일 이내에 확인해야 합니다.
기간이 1주일 미만인 선불 요금제는 요금제 기간의 절반 이내에 확인해야 합니다. 예를 들어 개발자는 1.5일 이내에 3일 선불 요금제를 확인해야 합니다.
딥 링크를 사용하여 사용자가 정기 결제를 관리하도록 허용
개발자는 고객이 정기 결제를 쉽게 관리할 수 있도록 해야 합니다. 사용자가 정기 결제를 관리할 수 있는 링크를 앱의 설정 또는 환경설정 화면에 포함해야 합니다. 이 링크의 예는 그림 4에 나와 있습니다.

사용자가 앱의 만료되지 않은 정기 결제를 보유하고 있는지 확인하는 로직을 이 링크의 클릭 핸들러에 추가합니다. 여기에서 expiryTime
가 미래 시점이거나 autoRenewing
이 true
로 설정됩니다.
각 정기 결제의 productId
는 Play Console에서 생성 시에 할당한 제품 ID와 일치합니다. 프로그래매틱 방식으로 기존 정기 결제의 productId
를 확인하려면 앱의 백엔드에 대해 특정 사용자와 관련된 정기 결제 목록을 쿼리합니다.
사용자에게 만료되지 않은 정기 결제가 있다면 'your-sub-product-id' 및 'your-app-package'를 정기 결제 ID 및 앱 패키지 정보로 바꿈으로써 다음과 유사한 URL로 사용자를 안내할 수 있습니다.
https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package
사용자에게 앱 내에 만료되지 않은 정기 결제가 없다면 다음 URL을 사용하여 그림 5 및 6과 같이 다른 정기 결제를 모두 보여주는 페이지로 사용자를 안내합니다.
https://play.google.com/store/account/subscriptions


Classy Taxi 샘플 앱에서 정기 결제 링크 로직의 코드 예를 확인할 수 있습니다.
사용자가 정기 결제를 업그레이드, 다운그레이드 또는 변경할 수 있도록 허용
기본 등급 및 프리미엄 등급과 같은 다양한 정기 결제 등급을 사용자에게 제공할 수 있습니다. 그림 7은 두 개의 정기 결제 등급을 제공하는 화면을 보여줍니다.

사용자가 정기 결제를 업그레이드하거나 다운그레이드하려면 그림 7과 유사한 화면에 액세스할 수 있어야 합니다. 정기 결제 업그레이드 또는 다운그레이드 시 변경사항이 정기 결제 사용자에게 영향을 주는 방식을 결정하는 비례 배분 모드를 설정할 수 있습니다.
다음 표에는 사용 가능한 비례 배분 모드가 나와 있습니다.
비례 배분 모드 | 설명 |
---|---|
IMMEDIATE_WITH_TIME_PRORATION |
정기 결제가 즉시 업그레이드 또는 다운그레이드됩니다. 남은 시간은 가격 차이를 기반으로 조정되며 다음 결제일을 앞당겨 새 정기 결제에 적립됩니다. 이것이 기본 동작입니다. |
IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
정기 결제가 즉시 업그레이드되며 결제 주기는 동일하게 유지됩니다. 남은 기간의 가격 차이는 사용자에게 청구됩니다. |
IMMEDIATE_WITHOUT_PRORATION |
정기 결제가 즉시 업그레이드 또는 다운그레이드되며 정기 결제가 갱신되면 새로운 가격이 청구됩니다. 결제 주기는 동일하게 유지됩니다. |
DEFERRED |
정기 결제가 갱신될 때만 업그레이드 또는 다운그레이드됩니다. |
IMMEDIATE_AND_CHARGE_FULL_PRICE |
정기 결제가 업그레이드되거나 다운그레이드되고 새 사용 권한과 관련된 전체 가격이 사용자에게 즉시 청구됩니다. 이전 정기 결제의 남은 값은 동일한 사용 권한에서는 이월되고, 다른 사용 권한으로 전환한 경우 시간에 따라 비례 배분됩니다. |
사용자가 정기 결제 사용 권한을 변경하는 경우 런타임에 비례 배분 비율을 지정해야 합니다. 사용 권한 변경의 경우 Google Play Console을 통해 기본 비례 배분 모드를 지정할 수 없습니다.
사용자가 정기 결제 사용 권한을 변경하지 않으면 Play Console을 통해 구성된 기본 비례 배분 모드를 사용할 수 있습니다. SubscriptionUpdateParams
에 비례 배분 모드를 지정하여 이 동작을 재정의할 수도 있습니다. 다음 제한사항을 참고하세요.
- 업그레이드하거나 다운그레이드하는 경우 또는 선불 요금제나 자동 갱신 요금제에서 선불 요금제로 동일한 정기 결제 전환을 실행하는 경우 허용되는 유일한 비례 배분 모드는
IMMEDIATE_AND_CHARGE_FULL_PRICE
입니다. 다른 비례 배분 모드를 지정하면 구매가 실패하고 사용자에게 오류가 표시됩니다. - 선불 요금제에서 자동 갱신 요금제로 동일한 정기 결제 내에서 요금제를 전환할 때 유효한 비례 배분 모드는
IMMEDIATE_AND_CHARGE_FULL_PRICE
와IMMEDIATE_WITHOUT_PRORATION
입니다. 다른 비례 배분 모드를 지정하면 구매가 실패하고 사용자에게 오류가 표시됩니다.
비례 배분 예
각 비례 배분 모드의 작동 방식을 이해하려면 다음 시나리오를 생각해 보세요.
샘와이즈는 Country Gardener 앱에서 온라인 콘텐츠를 정기 결제하고 있습니다. 그리고 현재 텍스트 전용 콘텐츠의 Tier 1 버전을 매월 정기 결제하고 있습니다. 이 정기 결제는 월 2달러의 요금이 청구되며 매월 1일에 갱신됩니다.
4월 15일에 샘와이즈는 동영상 업데이트가 포함되고 요금이 연 36달러인 연간 버전의 Tier 2 정기 결제로 업그레이드하기로 했습니다.
정기 결제를 업그레이드할 때 개발자는 비례 배분 모드를 선택합니다. 다음 목록에서는 각 비례 배분 모드가 샘와이즈의 정기 결제에 영향을 주는 방식을 설명합니다.
IMMEDIATE_WITH_TIME_PRORATION
- 샘와이즈의 Tier 1 정기 결제가 즉시 종료됩니다. 샘와이즈는 한 달(4월 1일~30일) 요금을 결제했는데 정기 결제 기간 중간에 업그레이드했으므로 월간 정기 결제 요금의 절반(1달러)은 새 정기 결제에 적용됩니다. 그러나 새 정기 결제 요금은 연간 36달러이므로 1달러의 잔액은 10일(4월 16일~25일)에 대해서만 결제됩니다. 따라서 4월 26일에 새 정기 결제의 요금으로 36달러가 청구되며, 다음 해부터 매년 4월 26일에 36달러가 청구됩니다.
IMMEDIATE_AND_CHARGE_PRORATED_PRICE
- 시간 단위당 Tier 2 정기 결제 요금($36/년 = $3/월)이 시간 단위당 Tier 1 정기 결제 요금($2/월)보다 크므로 이 모드를 사용할 수 있습니다. 샘와이즈의 Tier 1 정기 결제는 즉시 종료됩니다. 샘와이즈는 한 달 전체 요금을 결제했는데 기간의 절반만 사용했으므로 월간 정기 결제 요금의 절반(1달러)은 새 정기 결제에 적용됩니다. 그러나 새 정기 결제 요금은 1년에 36달러이므로 나머지 15일의 요금은 1.50달러입니다. 따라서 새 정기 결제 요금으로 0.50달러의 차액이 청구됩니다. 5월 1일에는 새 정기 결제 등급 요금으로 36달러가 청구되며, 다음 해부터 매년 5월 1일에 36달러가 청구됩니다.
IMMEDIATE_WITHOUT_PRORATION
- 샘와이즈의 Tier 1 정기 결제가 추가 비용 없이 Tier 2로 즉시 업그레이드됩니다. 그리고 5월 1일에 새 정기 결제 등급 요금으로 36달러가 청구되며, 다음 해부터 매년 5월 1일에 36달러가 청구됩니다.
DEFERRED
- 샘와이즈의 Tier 1 정기 결제는 4월 30일에 만료되기 전까지 계속됩니다. 5월 1일에 Tier 2 정기 결제가 적용되며, 새 정기 결제 등급 요금으로 36달러가 청구됩니다.
IMMEDIATE_AND_CHARGE_FULL_PRICE
- 샘와이즈의 Tier 1 정기 결제는 즉시 종료됩니다. Tier 2 정기 결제는 오늘 시작되어 36달러가 청구됩니다. 샘와이즈는 한 달 전체 요금을 결제했는데 기간의 절반만 사용했으므로 월간 정기 결제 요금의 절반(1달러)은 새 정기 결제에 적용됩니다. 새 정기 결제 요금이 연간 36달러이므로 일 년의 1/36일이 정기 결제 기간(최대 10일)에 추가됩니다. 따라서 다음번 청구는 오늘부터 1년 10일 후에 이루어지고 요금은 36달러입니다. 그 후에는 샘와이즈에게 다음 해부터 매년 36달러가 청구됩니다.
비례 배분 모드 선택 시 비례 배분 권장사항을 검토하세요.
앱은 구매 흐름 시작과 동일한 단계를 사용하여 사용자에게 업그레이드 또는 다운그레이드를 제공할 수 있습니다. 그러나 업그레이드 또는 다운그레이드할 때 다음 예와 같이 현재 정기 결제, 향후(업그레이드 또는 다운그레이드된) 정기 결제 및 사용할 비례 배분 모드에 관한 세부정보를 제공해야 합니다.
String offerToken = productDetails
.getSubscriptionOfferDetails(selectedOfferIndex)
.getOfferToken();
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(
ImmuableList.of(
ProductDetailsParams.newBuilder()
// fetched via queryProductDetailsAsync
.setProductDetails(productDetails)
// offerToken can be found in
// ProductDetails=>SubscriptionOfferDetails
.setOfferToken(offerToken)
.build()))
.setSubscriptionUpdateParams(
SubscriptionUpdateParams.newBuilder()
// purchaseToken can be found in Purchase#getPurchaseToken
.setOldSkuPurchaseToken("old_purchase_token")
.setReplaceSkusProrationMode(ProrationMode.IMMEDIATE_AND_CHARGE_FULL_PRICE)
.build())
.build();
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
// process purchase results from PurchasesUpdatedListener registered with BillingClient
public void onPurchaseUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases) {
// check BillingResult
// process returned Purchase list, e.g. grant entitlement
}
즉시 대체 비례 배분 모드의 경우 앱은 PurchasesUpdatedListener
에서 새 구매를 수신합니다.
또한 구매는 BillingClient.queryPurchasesAsync()
에서도 사용할 수 있습니다.
구매 토큰을 수신할 때는 새 구매 토큰 인증 시와 동일한 인증 프로세스를 따릅니다. Google Play 결제 라이브러리의 BillingClient.acknowledgePurchase()
또는 Google Play Developer API의 Purchases.subscriptions:acknowledge
를 사용하여 이러한 구매를 확인해야 합니다.
Google Play Developer API는 정기 결제 리소스에서 linkedPurchaseToken
을 반환합니다.
linkedPurchaseToken
에서 제공된 토큰을 무효화하여 서비스 액세스 권한을 얻는 데 이전 토큰이 사용되지 않도록 해야 합니다. 구매 업그레이드 및 다운그레이드 처리에 관한 자세한 내용은 업그레이드, 다운그레이드, 재등록을 참고하세요.
지연된 대체 모드의 경우 앱은 원래 정기 결제 요금제 구매 및 업그레이드 또는 다운그레이드 성공 여부 상태와 함께 PurchasesUpdatedListener
호출을 수신합니다. 대체가 적용될 때까지 BillingClient.queryPurchasesAsync()
는 원래 정기 결제 요금제의 구매를 계속 반환합니다. 새 요금제가 적용되면 queryPurchasesAsync()
는 새로운 정기 결제의 구매 데이터를 반환하고 SUBSCRIPTION_RENEWED
알림이 보안 백엔드 서버로 전송됩니다. 대체가 지연된 경우 이 알림을 수신 대기하고 Purchases.subscriptions:acknowledge
를 사용하여 구매를 확인하는 것이 좋습니다.
정기 결제 리소스의 linkedPurchaseToken
을 사용하면 정기 결제 백엔드에서(해당하는 경우) 새 자격으로 업데이트해야 할 사용자를 결정할 수 있습니다. 사용자가 요금제 변경이 적용된 후 3일 이내에 앱을 열지 않을 수 있으므로 앱은 사용자가 앱을 열고 BillingClient.acknowledgePurchase()
를 통해 확인하는 것에 의존해서는 안 됩니다.
무료 체험판 또는 신규 할인 가격 혜택으로 업그레이드
무료 체험판 자격요건 설정은 사용자가 업그레이드 또는 다운그레이드할 때 적용됩니다. Google Play Console에서 무료 체험판 자격요건 설정을 조정할 수 있습니다.
다음 내용을 참고하세요.
- 사용자가 앱에서 사용 가능한 모든 정기 결제와 관련하여 하나의 무료 체험판만 받을 수 있다면 사용자가 변경하려는 요금제에는 무료 체험판 또는 신규 할인 가격 혜택이 적용될 수 없습니다.
- 정기 결제 제품당 하나의 무료 체험판을 제공한다면 사용자가 변경하려는 요금제에는 무료 체험판 또는 신규 할인 가격이 적용될 수 있습니다.
다음 표에서는 새 요금제와 이전 요금제에 모두 무료 체험판이 포함되어 있으며 사용자가 무료 체험판 기간에 업그레이드할 때 각 비례 배분 모드의 동작을 설명합니다.
앱당 무료 체험판 1개 | 정기 결제 제품당 무료 체험판 1개 | |
IMMEDIATE_WITH_TIME_PRORATION | 사용자는 무료 체험판 혜택을 즉시 잃게 됩니다. 남은 무료 체험판 이용 기간은 가격 차이에 따라 새 등급의 무료 기간으로 전환됩니다. | 사용자가 이전 무료 체험판 혜택을 잃게 되지만 새 무료 체험판 혜택은 즉시 시작됩니다. 또한 이전 등급의 남은 무료 체험판 이용 기간은 새 등급의 상응하는 무료 기간으로 전환되며 새로운 무료 체험판에 추가됩니다. |
IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
사용자는 무료 체험판 혜택을 즉시 잃게 됩니다. 남은 기간의 가격 차이는 사용자에게 청구됩니다. 다음 결제일은 그대로 유지됩니다. 참고: 이 옵션은 시간 단위당 가격이 상승하는 정기 결제 업그레이드에만 사용할 수 있습니다. |
|
IMMEDIATE_WITHOUT_PRORATION | 사용자가 새 등급으로 즉시 업그레이드됩니다. 사용자는 이전 결제 기간이 종료될 때까지 새 등급에 대한 무료 체험판 액세스 권한을 유지합니다. | |
DEFERRED | 사용자는 다음 결제일까지 이전 정기 결제에 대한 무료 체험판 액세스 권한을 유지합니다. | |
IMMEDIATE_AND_CHARGE_FULL_PRICE | 사용자는 무료 체험판 혜택을 즉시 잃게 됩니다. 그런 다음 새 정기 결제 가격이 사용자에게 청구됩니다. 다음 청구일은 새 정기 결제 기간에 남은 무료 체험판 기간을 더한 값입니다. |
기본적으로 앱당 하나의 무료 체험판이 적용되는 경우 무료 체험판 전환이 작동하는 방식을 이해하려면 다음 시나리오를 생각해 보세요.
마리아는 Country Gardener 앱에서 온라인 콘텐츠를 정기적으로 결제하고 있습니다. 그리고 현재 텍스트 전용 콘텐츠의 Tier 1 버전을 매월 정기 결제하고 있습니다. 이 정기 결제 요금은 월 10달러이며, 마리아는 4월 1일에 정기 결제를 시작했습니다. 마리아는 정기 결제를 처음 시작한 사용자로 30일 무료 체험판 혜택을 누리고 있으며 이는 첫 번째 결제가 5월 1일로 예정되어 있음을 의미합니다.
4월 15일에 마리아는 동영상 업데이트가 포함되며 요금이 월 20달러인 Tier 2 정기 결제로 업그레이드하기로 했습니다. 이 두 번째 정기 결제에도 30일 무료 체험판 혜택이 있습니다.
다음 목록은 각 비례 배분 모드의 무료 체험판 전환 방식을 설명합니다.
IMMEDIATE_WITH_TIME_PRORATION
- 마리아는 Tier 2로 즉시 업그레이드됩니다. 마리아가 정기 결제 기간 중간에 업그레이드했으므로 월간 정기 결제 요금의 절반(월 10달러의 요금에서 15일분)은 새 정기 결제에 적용됩니다. 그러나 새 정기 결제 요금은 월 20달러이므로 15일의 잔액으로는 7.5일분만 결제할 수 있습니다. 마리아는 Tier 2에 대한 또 다른 무료 체험판을 사용할 수 없으므로 4월 22일부터 매월 20달러가 청구됩니다.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
- 시간 단위당 Tier 2 정기 결제 가격($20/월)이 시간 단위당 Tier 1 정기 결제 가격($10/월)보다 크므로 이 모드를 사용할 수 있습니다. 마리아의 Tier 1 정기 결제가 Tier 2로 즉시 업그레이드되며, 마리아는 무료 체험판 혜택을 잃게 됩니다. 마리아의 다음 결제일이 5월 1일이었으므로 4월 하반기의 요금으로 10달러가 오늘 청구되며, 이후 5월 1일부터 매월 20달러가 청구됩니다.IMMEDIATE_WITHOUT_PRORATION
- 마리아의 Tier 1 정기 결제가 Tier 2로 즉시 업그레이드됩니다. 마리아는 4월 30일까지 무료 체험판 혜택을 유지하며 이제 Tier 2 콘텐츠에 액세스할 수 있습니다. 5월 1일부터 매월 20달러가 청구됩니다.DEFERRED
- 마리아의 Tier 1 정기 결제는 다음 결제일인 5월 1일이 될 때까지 계속됩니다. 5월 1일에 Tier 2 정기 결제가 적용되며, 매월 1일에 마리아에게 20달러가 청구됩니다.IMMEDIATE_AND_CHARGE_FULL_PRICE
- 마리아의 Tier 1 정기 결제가 Tier 2로 즉시 업그레이드되며, 마리아는 무료 체험판 혜택을 잃게 됩니다. 오늘 마리아에게 20달러가 청구됩니다. 마리아에게 무료 체험판 기간이 15일 남았으므로 다음 청구일은 지금으로부터 1개월에 15일을 더한 7월 1일이 됩니다. 7월 1일부터 매월 20달러가 청구됩니다.
다음 목록은 개발자가 정기 결제당 하나의 무료 체험판을 허용하는 경우의 전환 동작을 설명합니다.
IMMEDIATE_WITH_TIME_PRORATION
- 마리아는 Tier 2로 즉시 업그레이드됩니다. 마리아가 정기 결제 기간 중간에 업그레이드했으므로 월간 정기 결제 요금의 절반(월 10달러의 요금에서 15일분)은 새 정기 결제에 적용됩니다. 그러나 새 정기 결제 요금은 월 20달러이므로 15일의 잔액으로는 7.5일분만 결제할 수 있습니다. 마리아는 Tier 2에 대한 또 다른 무료 체험판을 사용할 수 있으므로 37.5일 동안에는 요금이 청구되지 않습니다. 5월 22일부터 매월 20달러가 청구됩니다.IMMEDIATE_AND_CHARGE_PRORATED_PRICE
- 시간 단위당 Tier 2 정기 결제 가격($20/월)이 시간 단위당 Tier 1 정기 결제 가격($10/월)보다 크므로 이 모드를 사용할 수 있습니다. 마리아의 Tier 1 정기 결제가 Tier 2로 즉시 업그레이드되며, 마리아는 무료 체험판 혜택을 잃게 됩니다. 마리아의 다음 결제일이 5월 1일이었으므로 4월 하반기의 요금으로 10달러가 오늘 청구되며, 이후 5월 1일부터 매월 20달러가 청구됩니다.IMMEDIATE_WITHOUT_PRORATION
- 마리아의 Tier 1 정기 결제가 Tier 2로 즉시 업그레이드됩니다. 마리아는 4월 30일까지 무료 체험판을 계속 이용할 수 있으며 이제 Tier 2에 액세스할 수 있습니다.DEFERRED
- 마리아의 Tier 1 정기 결제는 다음 결제일인 5월 1일이 될 때까지 계속됩니다. 5월 1일에 Tier 2 정기 결제가 적용되며, 매월 1일에 마리아에게 20달러가 청구됩니다.IMMEDIATE_AND_CHARGE_FULL_PRICE
- 마리아의 Tier 1 정기 결제가 Tier 2로 즉시 업그레이드되며, 마리아는 무료 체험판 혜택을 잃게 됩니다. 오늘 마리아에게 20달러가 청구됩니다. 마리아에게 무료 체험판 기간이 15일 남았으므로 다음 청구일은 지금으로부터 1개월에 15일을 더한 7월 1일이 됩니다. 7월 1일부터 매월 20달러가 청구됩니다.
비례 배분 권장사항
다음 표는 다양한 비례 배분 시나리오와 함께 각 시나리오에 권장되는 사항을 보여줍니다.
시나리오 | 권장 비례 배분 모드 | 결과 |
---|---|---|
비용이 더 많이 드는 등급으로 업그레이드 | IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
사용자는 동일한 결제 기간을 유지하면서 즉시 액세스 권한을 받습니다. |
비용이 더 적게 드는 등급으로 다운그레이드 | DEFERRED |
사용자는 비용이 더 많이 드는 등급에 대해 이미 결제했으므로 다음 결제일까지 액세스 권한을 유지합니다. |
동일한 등급의 반복 기간 변경(예: 월간에서 연간으로) | DEFERRED |
사용자는 다음 결제일에 새로운 반복 가격을 지급합니다. |
무료 체험판 사용 중 업그레이드하고, 무료 체험판 유지 | IMMEDIATE_WITHOUT_PRORATION |
사용자는 무료 체험판 액세스 권한을 유지하지만 남은 무료 체험판 기간에 대해 더 높은 등급으로 업그레이드합니다. |
무료 체험판 사용 중 업그레이드 - 무료 체험판 액세스 종료 | IMMEDIATE_AND_CHARGE_PRORATED_PRICE |
사용자는 새 등급에 즉시 액세스할 수 있지만 무료 체험판을 더 이상 사용할 수 없습니다. |
고객 관리
실시간 개발자 알림을 사용하면 사용자가 취소하기로 결정한 시점을 실시간으로 감지할 수 있습니다. 사용자가 정기 결제를 취소했지만 정기 결제가 만료되기 전에 사용자에게 푸시 알림 또는 인앱 메시지를 보내 정기 결제를 재신청하도록 요청할 수 있습니다.
사용자가 정기 결제를 취소한 후 개발자는 앱에서 또는 Play 스토어를 통해 사용자를 재확보할 수 있습니다. 다음 표에서는 다양한 정기 결제 시나리오와 함께 관련 사용자 재확보 작업 및 앱 요구사항을 설명합니다.
정기 결제 만료 전 | 정기 결제 만료 후 | |||
인앱 | Play 스토어 내에서 | 인앱 | Play 스토어 내에서 | |
재확보 특징 | 인앱 정기 결제 | 복원 | 인앱 정기 결제 | 정기 결제 재신청 |
사용자가 결제 흐름을 거치는지 여부 | 예 | 아니요 | 예 | 예 |
사용자의 정기 결제가 동일한 SKU와 연결된 상태로 유지되는지 여부 | 사용자가 동일 SKU 또는 다른 SKU에 가입할 수 있음 | 예 | 사용자가 동일 SKU 또는 다른 SKU에 가입할 수 있음 | 예 |
새 구매 토큰 생성 여부 | 예 | 아니요 | 예 | 예 |
기본적으로 사용 설정되는지 여부 | 아니요 | 예, 모든 개발자에게 필요한 지원 | 아니요 |
결제 라이브러리 2.0 이상이 없는 앱: 아니요 결제 라이브러리 2.0 이상이 있는 앱: 예, 개발자는 콘솔에서 선택 해제할 수 있음 |
사용자에게 청구되는 시점 |
동일한 SKU를 사용하는 경우: 현재 결제 기간 종료 시 다른 SKU를 사용하는 경우: 비례 배분 모드에 따라 다름 |
현재 결제 기간 종료 시 | 즉시 | 즉시 |
필요한 구현 | 앱 내 재가입 UI 제공 |
정기 결제 상태 변경 감지 Play 스토어 딥 링크 |
앱 내 재가입 UI 제공 | 앱 외부 구매 처리 |
정기 결제 만료 전 - 앱 내에서
취소되었지만 아직 만료되지 않은 정기 결제의 경우 새 정기 결제 사용자와 동일한 인앱 상품 구매 흐름을 적용함으로써 정기 결제 사용자가 앱 내에서 정기 결제를 복원하도록 할 수 있습니다. UI가 사용자에게 기존 정기 결제가 있다는 점을 반영하는지 확인합니다. 예를 들어 재활성화 버튼을 사용하여 사용자의 현재 만료일 및 반복 가격을 표시할 수 있습니다.
일반적으로 개발자는 다음과 같이 사용자가 이미 정기 결제한 SKU 및 동일한 가격을 사용자에게 제공하려고 합니다.
- 동일한 SKU를 사용하여 새 정기 결제 구매를 시작합니다.
- 새 정기 결제는 이전 정기 결제를 대체하고 동일한 만료일에 갱신됩니다. 이전 정기 결제는 즉시 만료된 것으로 표시됩니다.
- 예를 들어 아킬레스가 Example Music App을 정기 결제하고 있으며, 이 정기 결제는 8월 1일에 만료될 예정이라고 가정해 보겠습니다. 아킬레스는 7월 10일에 1개월 정기 결제를 동일한 월별 가격으로 다시 결제합니다. 그러면 새 정기 결제는 나머지 잔액으로 비례 배분되고, 즉시 활성화되며, 여전히 8월 1일에 갱신됩니다.
새로운 무료 체험판 또는 재가입 할인과 같은 다른 가격을 제공하려는 경우 다음과 같이 사용자에게 다른 SKU를 제공하면 됩니다.
- 비례 배분 모드
IMMEDIATE_WITHOUT_PRORATION
을 사용하여 다른 SKU로 업그레이드 또는 다운그레이드를 시작합니다. - 새 정기 결제는 이전 정기 결제를 대체하고 동일한 만료일에 갱신됩니다. 원래 만료일에 신규 할인 가격을 포함한 새 SKU 가격이 사용자에게 청구됩니다. 난독화된 계정 ID를 사용하여 이전 정기 결제가 생성된 경우 같은 ID를 업그레이드와 다운그레이드를 위해
BillingFlowParams
에 전달해야 합니다. - 예를 들어 아킬레스가 Example Music App을 정기 결제하고 있으며, 이 정기 결제는 8월 1일에 만료될 예정이라고 가정해 보겠습니다. 7월 10일에 그는 연간 정기 결제를 신규 할인 가격으로 다시 결제합니다. 새 정기 결제가 즉시 활성화되며, 8월 1일에 신규 할인 가격이 사용자에게 청구됩니다.
- 재가입 SKU에 무료 체험판 또는 신규 할인 가격을 포함하기로 했다면 Google Play Console에서 사용자가 앱당 하나의 무료 체험판을 받도록 제한하는 옵션인 앱당 하나의 무료 체험판 허용 체크박스를 선택 해제하여 사용자가 자격요건을 충족하도록 합니다.
구매 토큰을 받으면 새 정기 결제에서와 마찬가지로 구매를 처리합니다. 또한 Google Play Developer API는 정기 결제 리소스에서 linkedPurchaseToken
을 반환합니다. linkedPurchaseToken
에서 제공된 토큰을 무효화하여 서비스 액세스 권한을 얻는 데 이전 토큰이 사용되지 않도록 해야 합니다.
정기 결제 만료 전 - Play 스토어에서
정기 결제가 취소되었지만 아직 활성 상태인 동안 사용자는 정기 결제 재신청(이전의 복원)을 클릭하여 Google Play 정기 결제 센터에서 정기 결제를 복원할 수 있습니다. 이렇게 하면 동일한 정기 결제 및 구매 토큰이 유지됩니다.

정기 결제 복원에 관한 자세한 내용은 복원을 참고하세요.
정기 결제 만료 후 - 앱 내에서
새 정기 결제 사용자와 동일한 인앱 상품 구매 흐름을 적용함으로써 만료된 정기 결제 사용자가 앱 내에서 정기 결제를 재신청하도록 할 수 있습니다. 다음 내용을 참고하세요.
- 사용자에게 할인을 제공하려면 정기 결제에 특별 가격이 적용된 제품 ID(재가입 SKU라고도 함)를 제공하는 것이 좋습니다. 앱 내에서 쿠폰을 제공하거나 이메일과 같이 앱 외부에서 사용자에게 쿠폰을 알릴 수 있습니다.
- 정기 결제 재가입을 시작하려면 Google Play 결제 라이브러리를 사용하여 Android 앱에서 구매 흐름을 시작합니다. 이 흐름은 새 정기 결제와 동일한 프로세스이지만, 사용자에게 제공할 SKU를 결정할 수 있습니다.
- 재가입 SKU에 무료 체험판 또는 신규 할인 가격을 포함하기로 했다면 Google Play Console에서 사용자가 앱당 하나의 무료 체험판을 받도록 제한하는 옵션인 앱당 하나의 무료 체험판 허용 체크박스를 선택 해제하여 사용자가 자격요건을 충족하도록 합니다.
- 사용자가 동일한 SKU로 정기 결제를 재개하면 더 이상 무료 체험판 또는 신규 할인 가격을 사용할 수 없습니다. UI에 이 사항이 반영되었는지 확인합니다.
구매 토큰을 받으면 새 정기 결제에서와 마찬가지로 구매를 처리합니다. 정기 결제 리소스에서 linkedPurchaseToken
을 수신하지 않습니다.
정기 결제 만료 후 - Play 스토어에서
옵션이 사용 설정된 경우 사용자는 Google Play 정기 결제 센터에서 정기 결제 재신청을 클릭하여 만료 후 최대 1년 동안 동일한 SKU의 정기 결제를 다시 신청할 수 있습니다. 그러면 새 정기 결제 및 구매 토큰이 생성됩니다.

정기 결제 재신청은 앱 외부 구매로 간주되므로 앱 외부에서 이루어진 구매 처리 권장사항을 따라야 합니다.
정기 결제 프로모션
프로모션 코드를 만들어 기존 정기 결제에 대한 연장된 무료 체험판을 선택된 사용자에게 제공할 수 있습니다. 자세한 내용은 프로모션 코드를 참고하세요.
무료 체험판의 경우 Google Play에서는 무료 체험판을 시작하기 전에 사용자에게 유효한 결제 수단이 있는지 인증합니다. 일부 사용자에게 이 인증은 결제 수단에 대한 보류 또는 청구로 표시될 수 있습니다. 이 보류 또는 청구는 일시적이며 나중에 취소 또는 환불됩니다.
무료 체험판 기간이 종료되면 사용자의 결제 수단으로 정식 정기 결제 금액이 청구됩니다.
사용자가 무료 체험판 기간에 언제든지 정기 결제를 취소하면 정기 결제는 무료 체험판이 끝날 때까지 활성 상태로 유지되며 무료 체험판 사용 기간이 종료되면 요금이 청구되지 않습니다.
취소 또는 환불, 해지
Google Play Developer API를 사용하여 정기 결제를 취소, 환불 또는 해지할 수 있습니다. 이 기능은 Google Play Console에서도 사용할 수 있습니다.
- 취소: 사용자가 Google Play에서 정기 결제를 취소할 수 있습니다. 또한 사용자가 앱 또는 웹사이트에서 취소할 수 있는 옵션을 제공할 수도 있습니다. 앱은 해지에 설명된 대로 이러한 취소를 처리해야 합니다.
- 환불: 개발자가 환불할 때 사용자는 정기 결제를 계속 사용할 수 있습니다. 예를 들어 사용자가 제품에 액세스하지 못하게 하는 기술적 오류가 발생했지만 오류가 해결된 경우 환불을 사용할 수 있습니다. 가장 최근 결제 금액을 초과하여 환불하거나 부분 환불을 처리하려면 Google Play Console을 사용해야 합니다.
- 해지: 개발자가 해지할 때 사용자는 정기 결제 액세스 권한을 즉시 잃게 됩니다. 예를 들어 사용자가 제품에 액세스하지 못하게 하는 기술적 오류가 발생했으며 사용자가 제품을 계속 사용하지 않으려는 경우에 이 기능을 사용할 수 있습니다. 앱은 해지에 설명된 대로 이러한 취소를 처리해야 합니다.
다음 표에서는 취소, 환불 및 해지의 차이점을 보여줍니다.
갱신 중지 | 환불 | 액세스 취소 | |
취소 | 예 | 아니요 | 아니요 |
환불 | 아니요 | 예 | 아니요 |
해지 | 예 | 예 | 예 |
정기 결제 사용자의 결제 연기
Google Play Developer API의 Purchases.subscriptions:defer
를 사용하여 자동 갱신 정기 결제 사용자의 다음 결제일을 연기할 수 있습니다. 연기 기간 동안 사용자는 전체 액세스 권한으로 정기 결제 콘텐츠에 액세스할 수 있지만 요금이 청구되지 않습니다. 정기 결제 갱신일은 새로운 날짜를 반영하여 업데이트됩니다.
선불 요금제의 경우 결제 연기 API를 사용하여 만료 시간을 연기할 수 있습니다.
결제 연기를 통해 다음을 할 수 있습니다.
- 영화 구매 1주일 무료 혜택 제공과 같은 특별 이벤트로 사용자에게 무료 액세스 권한을 부여합니다.
- 서비스 차원으로 고객에게 무료 액세스 권한을 부여합니다.
결제는 API 호출당 최소 하루, 최대 1년까지 연기할 수 있습니다. 결제를 훨씬 더 연기하려면 새 결제일이 도래하기 전에 API를 다시 호출하면 됩니다.
예를 들어 다르시가 Fishing Quarterly 앱의 온라인 콘텐츠를 매월 정기 결제하고 있으며 보통 매월 1일에 1.25파운드가 청구된다고 가정해 보겠습니다. 3월에 다르시는 앱 게시자에 관한 온라인 설문조사에 참여했습니다. 이에 대한 리워드로 게시자는 5월 15일(기존에 예정된 결제일인 4월 1일로부터 6주 후)까지 다음 결제를 연기함으로써 6주간 무료로 콘텐츠를 제공합니다. 4월 또는 5월 초 요금이 청구되지 않지만 다르시는 여전히 콘텐츠에 액세스할 수 있습니다. 5월 15일에는 월 정기 결제 비용으로 정상 요금인 1.25파운드가 청구됩니다. 다르시의 다음 갱신일은 이제 6월 15일입니다.
결제 연기 시 이메일을 통해 또는 앱 내에서 사용자에게 알림을 보내 결제일이 변경되었음을 알릴 수 있습니다.
결제 거부 처리
결제 주기가 끝날 때 결제 문제가 있는 경우 Google은 정기 결제를 취소하기 전에 한동안 정기 결제를 주기적으로 갱신하려고 합니다. 갱신 재시도는 최대 30일에 지정된 유예 기간을 합한 기간 만큼 지속될 수 있습니다. 또한 이 기간 동안 Google은 사용자에게 결제 수단 업데이트를 요청하는 이메일과 알림도 전송합니다.
결제가 거부되면 먼저 정기 결제에 유예 기간이 적용됩니다(사용 설정된 경우). 유예 기간 중에도 사용자는 계속해서 정기 결제 항목을 이용할 수 있어야 합니다.
유예 기간이 종료되면 정기 결제는 최대 30일 동안 계정 보류 상태가 됩니다. 계정 보류 기간에는 정기 결제 항목에 대한 액세스를 차단할 수 있습니다.
결제 거부 과정에서 정기 결제 복구 가능성을 극대화하기 위해 사용자에게 결제 문제를 알리고 문제 해결을 요청할 수 있습니다.
유예 기간 및 계정 보류 섹션에 설명된 대로 직접 이 작업을 실행하거나 Google에서 앱 사용자에게 메시지를 표시하도록 인앱 메시지 API를 구현할 수 있습니다.
인앱 메시지
InAppMessageCategoryId.TRANSACTIONAL
로 인앱 메시지를 사용 설정한 경우 Google Play에서는 유예 기간과 계정 보류 기간 동안 하루에 한 번씩 사용자에게 메시지를 표시하여 앱을 나가지 않고도 결제 문제를 해결할 기회를 제공합니다.

사용자가 앱을 열 때마다 이 API를 호출하여 메시지를 표시할지 결정하는 것이 좋습니다.
사용자가 정기 결제를 성공적으로 복구하면 구매 토큰과 함께 응답 코드 SUBSCRIPTION_STATUS_UPDATED
가 수신됩니다. 그러면 이 구매 토큰을 사용하여 Google Play Developer API를 호출하고 앱에서 정기 결제 상태를 새로고침해야 합니다.
인앱 메시지 통합
사용자에게 인앱 메시지를 표시하려면 BillingClient.showInAppMessages()
를 사용합니다.
다음은 인앱 메시지 흐름을 트리거하는 예시입니다.
Kotlin
val inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build() billingClient.showInAppMessages(activity, inAppMessageParams, object : InAppMessageResponseListener() { override fun onInAppMessageResponse(inAppMessageResult: InAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } })
Java
InAppMessageParams inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build(); billingClient.showInAppMessages(activity, inAppMessageParams, new InAppMessageResponseListener() { @Override public void onInAppMessageResponse(InAppMessageResult inAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } });