Register now for Android Dev Summit 2019!

정기 결제 관련 기능 추가

정기 결제는 Android Play Console을 사용하여 구성됩니다. 정기 결제를 구성한 후에는 앱에 Google Play 결제를 추가하여 정기 결제에 구매 흐름을 사용하도록 설정할 수 있습니다. 정기 결제에는 결제 기간, 유예 기간, 무료 체험판 등 Google Play 결제 개요에 언급된 다양한 특성이 있습니다. 이 섹션을 읽기 전에 이러한 개념을 잘 알고 있어야 합니다.

자세한 내용은 최신 정기 결제 동영상을 참조하세요.

또한 이 페이지의 나머지 부분을 읽기 전에 실시간 개발자 알림을 사용하도록 설정해야 합니다. 실시간 개발자 알림을 사용하면 상태 변화에 능동적으로 대처하고, 참여도를 높이며, 사용자 이탈을 줄일 수 있습니다. 실시간 개발자 알림을 사용하도록 설정하려면 실시간 개발자 알림을 참조하세요.

Google Play 결제 솔루션 전반에서 처리해야 할 몇 가지 정기 결제 사용 사례가 있습니다.

Google Play 결제 라이브러리, Google Play Developer API, 실시간 개발자 알림을 함께 사용하면 이러한 사용 사례를 해결할 수 있습니다.

실시간 개발자 알림으로 정기 결제 관련 상태 처리

실시간 개발자 알림은 SUBSCRIPTION_PURCHASED 또는 SUBSCRIPTION_RECOVERED 같은 정기 결제의 상태 변경을 모니터링할 수 있는 기능을 제공하는 서버 푸시 알림입니다. 실시간 개발자 알림을 사용하면 상태 변화에 능동적으로 대처하고, 참여도를 높이며, 사용자 이탈을 줄일 수 있습니다. 실시간 개발자 알림을 사용하도록 설정하려면 실시간 개발자 알림을 참조하세요.

실시간 개발자 알림을 사용하도록 설정한 경우, 보안 백엔드 서버는 정기 결제 상태 변화에 관한 알림만 수신합니다. 전체 상태를 파악하고 자체 백엔드 상태를 업데이트하려면 실시간 개발자 알림을 받은 후 개발자 API를 호출해야 합니다. 이 알림은 정기 결제 상태가 변경되었음을 알려줄 뿐, 정기 결제 상태에 대한 완전한 정보를 제공하지는 않습니다.

개발자 API를 확인할 때 항상 다음을 따라야 합니다.

  • expiryTimeMillis가 미래 시점인 경우 항상 자격을 부여합니다.
  • autoRenewing = false인 경우 만료 시간에 정기 결제가 종료되므로 사용자가 재가입하도록 유도합니다.
  • paymentState = 0인 경우 결제 문제를 해결하려면 정기 결제 센터 딥 링크를 사용하여 사용자를 정기 결제 센터로 보냅니다.

향후 Google에서는 정기 결제가 만료된 후 다시 활성화하는 등 사용자의 자격에 영향을 미치는 상태 변화를 추가할 수도 있습니다. 이러한 기능을 통합할 준비가 되었는지 확인하려면 개발자 API를 호출하고 위에서 설명한 대로 조치를 취하여 정의되지 않은 알림을 처리해야 합니다.

사용자가 유예 기간에 있음 - SUBSCRIPTION_IN_GRACE_PERIOD

유예 기간은 Google Play Console의 인앱 상품 설정에 따라 일정 기간 지속됩니다. Google Play에서는 유예 기간에 정기 결제를 갱신하려고 시도합니다. 사용자에게 결제 문제에 관해 알리려면 결제 수단을 수정하는 방법에 관한 안내 메시지를 앱에서 제공하세요. 그렇게 하지 않으면 사용자는 정기 결제에 대한 액세스 권한을 잃게 됩니다. 예를 들어 '계정 중단을 방지하려면 Google Play 정기 결제 설정으로 이동하여 Google Play에 대한 결제를 수정하세요.'라는 메시지를 Google Play 정기 결제 설정에 연결하여 사용자가 결제 수단을 수정할 수 있도록 합니다.

사용자의 유예 기간이 얼마나 긴지 확인하려면 Google Play Developer API를 호출하세요. Google Play에서는 유예 기간이 만료될 때까지 expiryTimeMillis 값을 동적으로 연장합니다. 이 기간에 사용자 정기 결제가 취소되었거나 갱신되었거나 보류 상태로 전환되었는지 확인해야 합니다. expiryTimeMillis가 경과한 후 사용자의 현재 정기 결제 상태를 확인하여 정기 결제의 최신 상태를 알아야 합니다.

JSON 응답의 내용은 다음 스니펫에 나와 있는 것처럼 정기 결제 상태에 따라 달라집니다. 예를 들어, 유예 기간에 정기 결제를 쿼리하는 경우(결제 방법이 불량) expiryTimeMillis는 미래의 타임스탬프로 동적 업데이트되고 paymentState는 0으로 설정됩니다.

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_future,
  "autoRenewing": true,
  ...
  "paymentState": 0  # Payment pending
}

정기 결제가 성공적으로 갱신된 후 결제를 쿼리하는 경우(결제 방법이 업데이트됨) expiryTimeMillis는 미래의 타임스탬프로 설정되고 paymentState는 1이 됩니다.

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_future,
  "autoRenewing": true,
  ...
  "paymentState": 1  # Payment received
}

유예 기간이 만료된 후 정기 결제를 쿼리하면 정기 결제 보류 중(Google Play Console에서 계정 보류를 사용하도록 설정한 경우)이거나 취소(Google Play Console에서 계정 보류를 사용하도록 설정하지 않은 경우)된 것을 확인할 수 있습니다. SUBSCRIPTION_ON_HOLDSUBSCRIPTION_CANCELLED의 샘플 JSON 응답은 계정 보류 - SUBSCRIPTION_ON_HOLD 섹션을 참조하세요.

계정 보류 - SUBSCRIPTION_ON_HOLD

계정 보류 기간은 30일 동안 지속됩니다. 계정 보류 중에 사용자 정기 결제가 취소되었거나, 복원되었거나, 다시 구매되었는지 확인해야 합니다. 계정 보류 중에 정기 결제 액세스가 정지된 이유를 사용자에게 알립니다. 사용자에게 알리려면 앱에서 결제 수단을 수정하고 정기 결제에 대한 액세스 권한을 다시 얻는 방법에 관한 안내 메시지를 제공하세요. 예를 들어, '정기 결제에 문제가 있습니다. Google Play 정기 결제 설정으로 이동하여 Google Play에 대한 결제를 수정하세요.'라는 메시지를 Google Play 정기 결제 설정에 연결하여 사용자가 결제 수단을 수정할 수 있도록 합니다. 또한 다음과 같은 조치도 취해야 합니다.

  • 사용자가 결제 방법을 업데이트하고 정기 결제가 복구되면, 결제한 콘텐츠에 대한 액세스 권한을 앱에서 복원해야 합니다. 자세한 내용은 정기 결제 복구됨 - SUBSCRIPTION_RECOVERED를 참조하세요. 그러나 이 보류 기간에 정기 결제가 복구되지 않으면 결제가 취소되며 사용자는 새 정기 결제를 구매해야 합니다.
  • 사용자가 앱에서 앱 외부에 있는 정기 결제에 액세스할 것으로 예상하는 경우, 푸시 알림이나 이메일을 보내 사용자에게 더 이상 정기 결제가 활성 상태가 아님을 알릴 수 있습니다. 사용자가 앱을 열 때만 정기 결제에 액세스할 수 있는 경우, 다음 번 사용자가 앱을 열 때 정기 결제 중단에 대해 알려야 할 수 있습니다.

계정이 아직 보류 상태인지 확인하려면 사용자가 앱에서 정기 결제한 콘텐츠에 액세스하려고 할 때마다 사용자의 현재 정기 결제 상태를 확인해야 합니다.

JSON 응답의 내용은 다음 스니펫에 나와 있는 것처럼 정기 결제 상태에 따라 달라집니다. 예를 들어, 계정 보류 중에 정기 결제를 쿼리하는 경우(결제 방법이 불량) expiryTimeMillis는 과거의 타임스탬프로 설정되고 paymentState는 0으로 설정됩니다.

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_past,
  "autoRenewing": true,
  ...
  "paymentState": 0  # Payment pending
}

정기 결제가 복구된 후 정기 결제를 쿼리하는 경우(결제 방법이 업데이트됨) expiryTimeMillis는 미래의 타임스탬프로 설정되고 paymentState는 1이 됩니다.

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_future,
  "autoRenewing": true,
  ...
  "paymentState": 1  # Payment received
}

보류가 30일간 지속되고 정기 결제가 취소된 후 정기 결제를 쿼리하는 경우 expiryTimeMillis는 과거의 타임스탬프로 설정되고 cancelReason은 1로 설정됩니다.

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": timestamp_in_past,
  "autoRenewing": false,
  ...
  "cancelReason": 1  # The system canceled the subscription
}

정기 결제 복구됨 - SUBSCRIPTION_RECOVERED

정기 결제를 복구한 후 일반적으로 구매 토큰은 사용자의 계정 보류가 시작되기 전과 동일합니다. 그러나 사용자는 보류 기간에 정기 결제를 다시 구매하여 결제한 콘텐츠에 대한 액세스 권한을 되찾았을 가능성도 있습니다. 이 경우 새 구매 토큰 값이 반환되어 정기 결제의 새 인스턴스를 나타냅니다.

서버에 새 정기 결제 데이터를 등록한 후, 사용자에게 정기 결제가 복원되었음을 알리는 메시지를 앱에 표시합니다. 예를 들어, '업데이트된 결제 방법이 기록되고 정기 결제가 복구되었습니다.'라는 메시지를 앱에 표시할 수 있습니다.

정기 결제 취소 - SUBSCRIPTION_CANCELLED

사용자는 Play 스토어에서 정기 결제를 자발적으로 취소하거나 보류 상태에서 복구하지 않음으로써 정기 결제가 자동으로 취소되도록 할 수도 있습니다. 보안 백엔드 서버에서 SUBSCRIPTION_CANCELLED 실시간 개발자 알림을 수신하는 경우 다음을 따르세요.

  • 사용자에게 정기 결제가 취소되었음을 알리는 메시지를 앱에 표시합니다. 예를 들어, '**some_date**에 정기 결제가 만료됩니다. Google Play 정기 결제 설정으로 이동하여 정기 결제를 복원하세요.'라는 메시지를 Google Play 정기 결제 설정에 연결하여 사용자가 정기 결제를 갱신할 수 있도록 합니다.
  • 사용자에게 이 메시지를 영구적으로 닫을 수 있는 기능을 제공해야 합니다.

새 구매 토큰을 받으면 구매 토큰 확인의 단계를 따르세요.

참고: 수동으로 정기 결제를 취소한 사용자의 경우 오래된 결제 방법으로 인해 취소된 경우와 달리 취소 메시지가 달갑지 않을 수 있습니다. 따라서 정기 결제를 수동으로 취소한 사용자에게는 알리지 않도록 선택할 수도 있습니다.

사용자가 정기 결제를 일시중지함 - SUBSCRIPTION_PAUSED

현재 일시중지된 정기 결제를 쿼리할 때 expiryTimeMillis가 과거 날짜이고 autoResumeTimeMillis는 미래 날짜인 경우 사용자의 콘텐츠 액세스 권한을 정지하고 사용자의 자격을 일시중지됨으로 간주해야 합니다.

{
  "kind": "androidpublisher#subscriptionPurchase",
  ...
  "expiryTimeMillis": $subscription_entitlement_end_time (in the past)
  "autoRenewing": true,
  "paymentState": 1  # Payment received
  ...
  "autoResumeTimeMillis": $subscription_auto_resume_time (in the future)
}

정기 결제 가격 변경

경고: Google을 통한 구독의 결제 가격을 변경하면 안 됩니다.

Google Play Console을 사용하면 앱에서 제공하는 정기 결제의 가격을 변경할 수 있습니다. 이 기능은 특정 정기 결제와 관련된 콘텐츠의 양 또는 인앱 혜택의 범위를 변경하는 경우에 유용합니다.

정기 결제 가격을 업데이트하려면 Google Play Console에서 다음 단계를 완료하세요.

  1. 가격을 변경할 정기 결제가 포함된 앱으로 이동합니다.
  2. 앱 정보 > 인앱 상품을 선택한 다음 정기 결제 탭을 엽니다.
  3. 그림 1과 같이 변경하려는 가격 옆에 있는 수정 링크를 선택합니다.

    정기 결제 가격 옆의 '수정' 링크
    그림 1. 구독 가격 필드 수정
  4. 구독에 적용하고자 하는 새로운 가격을 입력합니다.

    가격을 변경하면 그림 2와 같은 경고 대화상자가 나타납니다. 이 대화상자에서는 가격 변경이 새로운 정기 결제 사용자에게는 즉시 적용되고 가격 변경에 동의하는 기존 정기 결제 사용자에게는 30일 이내에 적용된다고 설명합니다.

    구독 가격 변경 경고 대화상자
    그림 2. 정기 결제 가격 변경이 적용되는 시기에 관한 경고

사용자에게 가격 변경 알리기

Google Play에서 알림을 시작하기 전 최소 7일간 기존 정기 결제 사용자에게 연락하여 가격 변경에 관해 알릴 수 있습니다. Google Play에서 사용자에게 알릴 경우 그림 3과 비슷한 대화상자가 표시됩니다. 이 대화상자에는 이전 가격, 새 가격, 새 가격이 적용되는 날짜가 표시됩니다.

일반 구독 가격 변경 대화상자
그림 3. 사용자에게 구독 가격 변경을 알리는 일반 대화상자

앱에서 다음과 같은 방법으로 이 대화상자를 표시할 수 있습니다.

가격 변경 확인 흐름 시작

앱이 시작될 때 대화상자를 표시하려면 결제 클라이언트 클래스에 다음 로직을 추가합니다.

Kotlin

val priceChangeFlowParams = PriceChangeFlowParams.newBuilder()
        .setSkuDetails(changedPriceSubscriptionSkuDetails)
        .build()

billingClient.launchPriceChangeConfirmationFlow(activity,
        priceChangeFlowParams,
        object : PriceChangeConfirmationListener() {
            override fun onPriceChangeConfirmationResult(responseCode: Int) {
                if (responseCode == BillingResponse.OK) {
                    // User has confirmed the price change.
                } else if (responseCode == BillingResponse.USER_CANCELED) {
                    // User hasn't confirmed the price change.
                }
            }
        })

자바

PriceChangeFlowParams priceChangeFlowParams = PriceChangeFlowParams.newBuilder()
        .setSkuDetails(changedPriceSubscriptionSkuDetails)
        .build();

billingClient.launchPriceChangeConfirmationFlow(activity,
        priceChangeFlowParams,
        new PriceChangeConfirmationListener() {
            @Override
            public void onPriceChangeConfirmationResult(int responseCode) {
                if (responseCode == BillingResponse.OK) {
                    // User has confirmed the price change.
                } else if (responseCode == BillingResponse.USER_CANCELED) {
                    // User hasn't confirmed the price change.
                }
            }
        });

Google Play의 가격 변경 대화상자를 표시하기 전에 가격 변경의 이유를 설명하는 자체 메시지 또는 대화상자를 제공할 수 있습니다. 이러한 유형의 맞춤 메시지를 만들어 표시하면 사용자가 새로운 가격으로 정기 결제 갱신을 선택할 가능성이 더 커집니다.

사용자 맞춤형 대화상자에 응답하면, 앱이 다시 활성화되고 Google Play 결제 라이브러리로부터 responseCode BillingClient.BillingResponse를 받습니다.

개발자는 PriceChangeConfirmationListener 구현에서 사용자 응답을 처리할 수 있습니다. 예를 들어 사용자가 가격 변경에 동의하면 맞춤 감사 메시지를 표시할 수 있습니다.

가격 변경에 관한 사용자 확인 처리

사용자가 새 정기 결제 가격을 수락하면, 라이브러리에서 결제 서버에 알림을 전송합니다. Google의 실시간 개발자 알림 기능을 통해 사용자가 대화상자에 어떻게 응답했는지에 관해 알림을 받을 수 있습니다. 사용자가 가격 변경을 수락하면 SUBSCRIPTION_PRICE_CHANGE_CONFIRMED 유형의 알림을 받습니다.

가격 변경이 거부된 경우 사례 처리

사용자가 앱의 PriceChangeConfirmationListener에서 가격 변경에 동의하지 않을 수 있습니다. 이 경우에는 고객이 다음 갱신 날짜에 만료될 때까지 기존 제품을 계속 사용할 수 있도록 하세요. 이전 정기 결제가 만료될 때까지 사용자가 가격 변경을 수락하지 않으면 사용자의 정기 결제가 취소되고, SUBSCRIPTION_CANCELED 유형의 실시간 개발자 알림을 수신하게 됩니다.

앱에서 정기 결제를 지원하는 경우 사용자가 정기 결제를 관리할 수 있도록 설정 또는 환경 설정 화면에 링크를 포함합니다. 이 링크의 예는 그림 4에 나와 있습니다. 사용자가 앱의 만료되지 않은 정기 결제를 보유하고 있는지 확인하는 로직을 링크의 클릭 핸들러에 추가합니다. 여기에서 expiryTimeMillis가 미래 시점이거나 autoRenewingtrue로 설정됩니다.

  • 사용자의 앱에 이러한 정기 결제가 없는 경우 그림 5와 같이 다음 URL을 사용하여 다른 정기 결제를 모두 표시하는 페이지로 사용자를 안내합니다.

    http://play.google.com/store/account/subscriptions
    
  • 반면, 사용자에게 만료되지 않은 정기 결제가 있는 경우, 그림 6과 같이 다음 URL을 사용하여 사용자를 만료되지 않은 정기 결제로 안내합니다.

    https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package
    

각 정기 결제의 SKU는 Play Console에서 만들 때 할당한 제품 ID와 일치합니다. 프로그래매틱 방식으로 기존 정기 결제의 SKU를 확인하려면 앱의 백엔드에서 특정 사용자와 관련된 정기 결제 목록을 쿼리합니다. 필수 서버 측 로직의 예로는 ClassyTaxi 샘플 앱에 있는 queryCurrentSubscriptions() 메서드를 참조하세요.

'Google Play 구독' 버튼이 포함된 설정 화면
그림 4. '정기 결제 관리' 링크의 예를 보여주는 Google Play 정기 결제 버튼 이미지
모든 앱에서 사용자의 구독을 보여주는 구독 세부정보 화면
그림 5. 사용자를 이 화면으로 보낸 앱 외부에서 사용자가 구매한 모든 정기 결제 내역을 보여주는 화면
사용자가 특정 앱에서 구매한 특정 구독을 보여주는 구독 세부정보 화면
그림 6. 사용자를 이 화면으로 보낸 앱에서 사용자가 구매한 특정 정기 결제의 세부정보를 보여주는 화면

정기 결제 업그레이드 또는 다운그레이드 허용

기본 등급 및 프리미엄 등급과 같은 다른 구독 등급을 사용자에게 제공할 수 있습니다. 그림 7은 두 개의 구독 등급을 제공하는 화면을 보여줍니다.

그림 7. 정기 결제 등급

다른 등급의 정기 결제를 구매한 사용자는 정기 결제를 업그레이드 또는 다운그레이드하기 위해 비슷한 화면에 액세스할 수 있어야 합니다. 인앱 상품의 구매 사용 설정에서 원래 정기 결제를 구매하는 데 사용한 것과 동일한 인앱 상품 구매 흐름을 사용하여 앱에서 이 사례를 처리해야 합니다. 그러나 업그레이드하거나 다운그레이드하면, setOldSku() 메서드를 사용하여 현재 정기 결제 및 미래(업그레이드되거나 다운그레이드된) 정기 결제의 제품 ID를 BillingFlowParams 개체에 전달합니다. 예:

Kotlin

val flowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(newSkuDetails)
        .setOldSku(currentId)
        .build()
val responseCode = billingClient.launchBillingFlow(activity, flowParams)

자바

BillingFlowParams flowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(newSkuDetails)
        .setOldSku(currentId)
        .build();
int responseCode = billingClient.launchBillingFlow(flowParams);

구매 토큰을 받으면 새 구매 토큰에 사용된 것과 동일한 확인 절차를 따르세요. 자세한 내용은 구매 확인을 참조하세요. Google Play Developer API는 정기 결제 리소스에 linkedPurchaseToken을 반환합니다. linkedPurchaseToken에 제공된 토큰을 무효화하여, 서비스에 액세스하는 데 이전 토큰이 사용되지 않도록 하세요.

사용자가 업그레이드하거나 다운그레이드하면 보안 백엔드 서버로 SUBSCRIPTION_PURCHASED 상태가 전송됩니다. SUBSCRIPTION_PURCHASED를 처리하려면 SUBSCRIPTION_PURCHASED 처리를 참조하세요.

비례 배분 모드 설정

정기 결제를 업그레이드하거나 다운그레이드할 때 BillingFlowParams 클래스에 replaceSkusProrationMode를 설정하여 정기 결제 변경 시 적용될 비례 배분에 관한 세부정보를 제공할 수 있습니다.

Kotlin

val flowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .setOldSku(oldSku)
        .setReplaceSkusProrationMode(replaceSkusProrationMode)
        .build()
val responseCode = billingClient.launchBillingFlow(activity, flowParams)

자바

BillingFlowParams flowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .setOldSku(oldSku)
        .setReplaceSkusProrationMode(replaceSkusProrationMode)
        .build()
int responseCode = billingClient.launchBillingFlow(activity, flowParams);

다음 표에는 모든 비례 배분 모드가 나열되어 있습니다.

IMMEDIATE_WITH_TIME_PRORATION 교체가 즉시 적용되며, 새로운 만료 시간은 비례 배분되어 사용자에게 환불되거나 청구됩니다. 이는 현재 기본 동작입니다.
IMMEDIATE_AND_CHARGE_PRORATED_PRICE 교체가 즉시 적용되며, 결제 주기는 동일하게 유지됩니다. 남은 기간에 대한 가격이 청구됩니다.

참고: 이 옵션은 정기 결제 업그레이드에만 사용할 수 있습니다.

IMMEDIATE_WITHOUT_PRORATION 교체가 즉시 적용되며, 다음번 반복에 새 가격이 부과됩니다. 결제 주기는 동일하게 유지됩니다.
DEFERRED 교체가 다음 반복 시 적용됩니다.

각 모드의 작동 방식을 이해하려면 다음 시나리오를 고려하세요.

Samwise는 Country Gardener 앱에서 온라인 콘텐츠를 정기적으로 결제하고 있습니다. 현재 텍스트 전용 콘텐츠가 있는 Tier 1 버전의 콘텐츠를 월간 정기 결제하고 있습니다. 결제료는 월 2달러이며 매월 1일에 갱신됩니다.

Samwise는 4월 15일에 동영상 업데이트가 포함되고 정기 결제료가 월 3달러인 Tier 2 정기 결제로 업그레이드하기로 선택했습니다.

정기 결제를 업그레이드할 때 개발자는 비례 배분 모드를 선택합니다. 다음 목록은 각 비례 배분 모드가 Samwise의 정기 결제에 미치는 영향을 나타냅니다.

  • IMMEDIATE_WITH_TIME_PRORATION: 이 모드를 사용하면 Samwise의 Tier 1 정기 결제가 즉시 종료됩니다. 그는 한 달(4월 1일~30일) 요금을 결제했지만 절반 기간만 사용했으므로 나머지 절반의 정기 결제료(1달러)는 새 정기 결제에 적용됩니다. 그러나 새 정기 결제료는 월 3달러이므로, 1달러의 잔액으로는 10일분만 결제할 수 있습니다. 따라서 Samwise는 잔액으로 4월 15일~25일의 정기 결제 요금을 결제합니다. 4월 26일에 새 정기 결제료로 3달러가 청구되며, 그 이후 매월 26일에 3달러가 청구됩니다.
  • IMMEDIATE_AND_CHARGE_PRORATED_PRICE: 이 모드를 사용하면 Samwise의 Tier 1 정기 결제가 즉시 종료됩니다. 그는 한 달(4월 1일~30일) 요금을 결제했지만 4월 중 절반 기간만 사용했으므로 나머지 절반의 정기 결제료(1달러)는 새 정기 결제에 적용됩니다. 그러나 새 정기 결제료는 월 3달러이므로 나머지 15일의 비용은 1.50달러입니다. 따라서 새 정기 결제의 차액으로 0.50달러가 청구되며, 그 이후에는 매월 1일에 3달러가 청구됩니다.
  • IMMEDIATE_WITHOUT_PRORATION: 이 모드를 사용하면 Samwise의 Tier 1 정기 결제가 추가 비용 없이 Tier 2로 즉시 업그레이드됩니다. 5월 1일에 새 정기 결제 등급 요금으로 3달러가 청구되고 그 이후 매월 1일에 3달러가 청구됩니다.
  • DEFERRED: 이 모드를 사용하면 Samwise의 Tier 1 정기 결제는 4월 30일에 만료될 때까지 계속됩니다. 5월 1일에 Tier 2 정기 결제가 시작되고 새 정기 결제 등급 요금으로 Samwise에게 3달러가 청구됩니다.

정기 결제 일시중지

사용자에게 정기 결제 일시중지 기능을 제공하여 자발적 앱 제거를 방지할 수 있습니다. 일시중지 기능을 사용하도록 설정하면 사용자가 반복 기간에 따라 일주일에서 3개월 사이에 일정 기간 정기 결제를 일시중지하도록 선택할 수 있습니다. 일시중지 옵션을 사용 설정하면 정기 결제 센터와 취소 흐름 모두에 이 옵션이 표시됩니다. 일주일과 3개월의 일시중지 한도는 언제든지 변경될 수 있습니다. 연간 정기 결제는 일시중지할 수 없습니다.

중요: 일시중지를 사용하도록 설정하려면 계정 보류 기능도 사용하도록 설정해야 합니다.

사용자가 정기 결제를 일시중지할 수 있게 하려면 다음 단계를 따르세요.

  1. Google Play Console에 로그인합니다.
  2. 앱을 선택한 다음 앱 정보 > 인앱 상품 > 정기 결제로 이동합니다.
  3. 정기 결제 설정 섹션을 펼칩니다.
  4. 일시중지 허용을 선택합니다.

정기 결제 일시중지는 현재 결제 기간이 지난 후에만 적용됩니다. 정기 결제가 일시중지된 동안 사용자는 정기 결제에 액세스할 수 없습니다. 일시중지 기간이 끝나면 정기 결제가 재개되고 Google에서 정기 결제 갱신을 시도합니다. 재개가 완료되면 정기 결제가 다시 활성화됩니다. 결제 문제로 정기 결제가 재개되지 않으면 그림 8과같이 사용자가 계정 보류 상태로 전환됩니다.

일시중지 상태에서 계정 보류 상태로의 전환을 보여주는 다이어그램
그림 8. 사용자가 정기 결제를 일시중지한 후 계정 보류 상태로 전환됩니다.

사용자는 그림 9에서와 같이 일시중지 기간에 언제든지 정기 결제를 수동으로 재개하도록 선택할 수 있습니다. 사용자가 정기 결제를 수동으로 재개하면 결제일이 수동 재개 날짜로 변경됩니다.

일시중지 상태에서 재개 상태로의 전환을 보여주는 다이어그램
그림 9. 사용자가 정기 결제를 일시중지한 후 재개합니다.

정기 결제가 일시중지되면 사용자가 앱에 있을 때 결제를 일시중지했기 때문에 정기 결제에 액세스할 수 없다고 알리는 것이 좋습니다. 또한 사용자에게 Google Play로 연결되는 딥 링크를 사용하여 정기 결제를 수동으로 재개할 수 있는 방법을 제공해야 합니다.

다음 메서드를 통해 정기 결제가 언제 일시중지되고 재개되는지 감지할 수 있습니다.

  • Google Play Developer API를 사용하여 Purchases.subscriptions 응답에서 expiryTimeMillisautoResumeTimeMillis 필드를 찾습니다.

    • 사용자가 대기 중인 일시중지 상태인 경우 expiryTimeMillisautoResumeTimeMillis 모두에 미래 날짜가 포함됩니다.
    • 사용자가 현재 일시중지 상태인 경우 autoResumeTimeMillis미래 날짜가, expiryTimeMillis과거 날짜가 포함됩니다.
    • 사용자가 정기 결제를 재개한 경우 응답에 활성 정기 결제 날짜가 포함됩니다.
    • 사용자가 계정 보류 상태로 전환된 경우 응답에 계정 보류 데이터가 포함됩니다.
  • 실시간 개발자 알림(RTDN)을 사용합니다. 최신 일시중지 정기 결제 정보를 받고 있는지 확인하려면, 인식되지 않는 유형을 비롯하여 모든 RTDN 알림 유형에 대한 응답으로 Google Play Developer API를 호출해야 합니다. 정기 결제 일시중지와 관련된 알림 유형은 다음과 같습니다.

    • SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED: 일시중지가 적용되기 전에 사용자가 정기 결제 일시중지 또는 재개를 선택했습니다.
    • SUBSCRIPTION_PAUSED: 현재 정기 결제가 일시중지되어 있습니다.
    • SUBSCRIPTION_RENEWED: 정기 결제가 재개되었습니다.
    • SUBSCRIPTION_ON_HOLD: 정기 결제를 재개하려고 했으나 실패했으며 현재 정기 결제가 계정 보류 상태입니다.
  • Android 기기에서 애플리케이션이 시작될 때마다 Google Play 결제 라이브러리를 사용해 queryPurchases()를 호출합니다. 앱이 실행되는 동안 PurchasesUpdatedListener를 사용해 업데이트를 받습니다. onPurchasesUpdated()Purchase 개체 목록에는 일시중지된 정기 결제가 포함되어 있지 않습니다.

정기 결제를 다시 결제하도록 허용

정기 결제가 아직 만료되지 않은 경우에도 사용자는 취소된 정기 결제를 다시 결제할 수 있습니다. 동일한 인앱 상품 구매 흐름을 동일한 제품 ID를 사용하는 취소된 정기 결제에 적용하여 사용자가 앱에서 다시 결제하도록 허용할 수 있습니다. 자세한 내용은 인앱 상품의 구매 사용 설정을 참조하세요.

새 정기 결제는 이전 정기 결제를 대체하며 동일한 만료일에 갱신됩니다. 예를 들어, Achilles가 Example Music App을 정기 결제하고 있다고 가정해 보겠습니다. 정기 결제는 현재 8월 1일에 만료될 예정입니다. 7월 10일에 1개월 정기 결제를 동일한 월 가격으로 다시 결제하면 새로운 정기 결제는 잔액으로 비례 배분되고, 즉시 활성화되며, 8월 1일에 갱신됩니다.

사용자가 다시 정기 결제할 수 있도록 적절한 UI를 표시해야 합니다.

  • 사용자에게 활성 상태인 정기 결제가 없는 경우 앱에 '구매' 버튼이 표시됩니다.
  • 사용자에게 취소된 정기 결제(SUBSCRIPTION_CANCELLED)가 있는 경우 앱에 '다시 정기 결제' 버튼을 표시할 수 있습니다. 자세한 내용은 SUBSCRIPTION_CANCELLED 처리를 참조하세요.

구매 토큰을 받으면 새 구매 토큰에 사용된 것과 동일한 확인 절차를 따르세요. 자세한 내용은 구매 확인을 참조하세요. Google Play Developer API는 정기 결제 리소스에 linkedPurchaseToken을 반환합니다. linkedPurchaseToken에서 제공된 토큰을 무효화하여, 서비스에 액세스하는 데 이전 토큰이 사용되지 않도록 하세요.

정기 결제용 프로모션 코드 제공

프로모션 또는 프로모션 코드를 사용하면 한정된 수의 사용자에게 일회성 제품이나 정기 결제 체험판을 무료로 제공할 수 있습니다. 정기 결제 체험판의 프로모션 코드를 구현하려면 프로모션 구현을 참조하세요.

정기 결제료 환불

Google Play에서는 정기 결제 환불 창을 제공하지 않습니다. 대신 사용자가 직접 환불을 요청해야 합니다. 사용자는 Play 스토어의 내 주문 페이지를 사용하거나 개발자에게 직접 연락하여 환불을 요청할 수 있습니다.

환불 요청을 받으면 Google Play Developer API 또는 판매자 센터를 사용하여 다음을 진행할 수 있습니다.

  1. 정기 결제를 취소(Purchases.subscriptions:cancel)합니다.
  2. 정기 결제가 취소되었는지 확인(HTTP 응답 코드 200 반환)(Purchases.subscriptions:cancel)합니다.
  3. 정기 결제를 취소하지 않고 사용자가 결제한 금액을 환불(Purchases.subscriptions:refund)합니다.

최근 결제 금액보다 많은 금액을 환불하려는 경우에는 판매자 센터를 통해 추가 환불을 처리할 수 있습니다.

정기 결제가 취소되면 보안 백엔드 서버로 SUBSCRIPTION_CANCELLED 상태가 전송됩니다. SUBSCRIPTION_CANCELLED를 처리하려면 SUBSCRIPTION_CANCELLED 처리를 참조하세요.

정기 결제 철회

Google Play Developer API를 사용하면 Purchases.subscriptions:revoke를 사용해 정기 결제를 철회할 수 있습니다. 정기 결제를 철회하면 정기 결제에 대한 액세스 권한이 즉시 삭제됩니다. 정기 결제 철회는 대개 개발자 또는 Google에서 사기를 의심하는 경우 진행됩니다.

정기 결제 취소

사용자는 Play 스토어 앱에서도 정기 결제를 취소할 수 있습니다. Google Play Developer API를 사용하면 Purchases.subscriptions:cancel을 사용해 정기 결제를 취소할 수 있습니다.

참고: 이 API는 보통 사용자가 내 주문 페이지에서 환불을 요청할 때 사용됩니다. 자세한 내용은 정기 결제료 환불을 참조하세요.

사용자는 현재 결제 주기가 끝날 때까지 콘텐츠에 대한 액세스 권한을 보유합니다. 결제 주기가 끝나면 액세스 권한이 철회됩니다.

중요: 사용자가 콘텐츠에 대한 권한을 보유하고 있는 동안에는 Google Play에서 정기 결제를 삭제해서는 안 됩니다. 사용자에게 제공해야 할 콘텐츠를 삭제하면 벌금이 부과될 수 있습니다. 자세한 내용은 정기 결제 만들기의 취소 섹션을 참조하세요.

정기 결제 복원

참고: 2019년 4월 15일부터 모든 앱에서 일관된 사용자 환경을 제공하기 위해, Google에서는 정기 결제를 사용하는 모든 개발자가 기본적으로 복원 기능을 사용하도록 설정하고 있습니다. 이 날짜 이전에 복원 기능을 테스트하여 복원을 올바르게 처리할 수 있는지 확인하는 것이 좋습니다. 더욱 원활한 전환을 위해 Google에서는 모든 라이선스 테스트 계정에 복원을 사용하도록 설정했습니다. 정기 결제 테스트에 관한 자세한 내용은 정기 결제 관련 기능 테스트를 참조하세요.

코드를 변경해야 하지만 2019년 4월 15일 전에 완료할 수 없는 경우, Google Play Console에서 앱 정보 > 인앱 상품 > 정기 결제 설정으로 이동한 다음 사용자가 Google Play에서 정기 결제를 복원하도록 허용의 선택을 해제할 수 있습니다. 2019년 4월 15일에 변경이 적용된 후에 선택 해제해도 됩니다.

취소된 정기 결제는 만료일까지 Play 스토어 앱에 계속 표시됩니다. 사용자는 Play 스토어 앱의 계정 > 정기 결제 섹션에서 복원을 클릭하여 취소된 정기 결제를 복원할 수 있습니다.

그림 10. Play 스토어 앱의 계정 > 정기 결제 섹션

정기 결제가 복원된 경우 다음 두 가지 방법으로 감지할 수 있습니다.

  1. 앱에 SUBSCRIPTION_RESTARTED 알림이 전송됩니다. 자세한 내용은 실시간 개발자 알림을 참조하세요.
  2. 애플리케이션이 열릴 때마다 getPurchases() 메서드를 호출할 수 있습니다. 정기 결제가 복원된 후 purchaseToken은 정기 결제가 취소되기 전과 동일하게 유지됩니다.

사용자가 취소된 정기 결제를 복원할 수 있도록 하려면 다음을 따르세요.

  1. Google Play Console에 로그인합니다.
  2. 앱을 선택한 다음 앱 정보 > 인앱 상품으로 이동합니다.
  3. 정기 결제 탭을 선택한 다음 정기 결제 설정 섹션을 확장합니다.
  4. 그림 11에 나와 있는 것처럼 사용자가 Google Play에서 정기 결제를 복원하도록 허용 체크박스를 선택한 다음 저장을 클릭합니다.
    그림 11. Google Play Console의 정기 결제 복원 활성화 체크박스

결제 연기

Google Play Developer API를 사용하면 Purchases.subscriptions:defer를 사용해 정기 결제 사용자의 다음 결제일을 조정할 수 있습니다. 사용자는 콘텐츠의 정기 결제를 계속하고 전체 액세스 권한을 갖지만, 연기된 기간에는 비용이 청구되지 않습니다. 정기 결제 갱신일은 새로운 날짜를 반영하여 업데이트됩니다. 결제를 연기하여 다음을 할 수 있습니다.

  • 실물 잡지를 정기 결제하는 사용자에게 웹 콘텐츠에 무료로 액세스할 권한을 주는 등 번들 또는 특별 이벤트의 일환으로 무료 액세스 권한을 부여합니다.
  • 서비스 차원에서 고객에게 무료 액세스 권한을 부여합니다.

결제는 API 호출당 최소 하루, 최대 1년 연기할 수 있습니다. 결제를 더 연기하려면 새 결제일이 도래하기 전에 API를 다시 호출하세요.

예를 들어 Darcy가 Fishing Quarterly 앱의 온라인 콘텐츠를 월간 정기 결제하고 있다고 가정해 보겠습니다. 일반적으로 매월 1일에 1.25파운드가 청구됩니다. 그러던 중 Darcy가 3월에 앱 게시자가 실시하는 온라인 설문조사에 참여하여 이에 대한 리워드로 게시자가 5월 15일(기존 예약 결제일인 4월 1일로부터 6주 후)까지 결제를 연기하여 6주간 무료로 콘텐츠를 제공합니다. 4월 또는 5월 초에 요금이 부과되지 않지만 Darcy는 여전히 콘텐츠에 액세스할 수 있습니다. 5월 15일에는 월 정기 결제료 1.25파운드가 청구되고, 다음 갱신일은 6월 15일이 됩니다.

이메일을 통하거나 앱에서 사용자에게 알림을 보내 결제일이 연기(변경)되었음을 알리는 것이 좋습니다.

고객을 다시 확보

충성도가 높은 고객이 오랜 시간 정기 결제 후에 서비스를 종료하는 경우, 특별 정기 결제료를 나타내는 제품 ID(winback SKU라고도 함)를 제공할 수 있습니다. 앱에서 쿠폰을 제공할 수도 있고 이메일로 사용자에게 쿠폰을 알릴 수도 있습니다. 정기 결제 다시 확보를 시작하려면 Google Play 결제 라이브러리를 사용하여 Android 앱에서 구매 흐름을 시작하세요. 이 흐름은 새 정기 결제와 동일한 절차이지만, 사용자에게 제공할 SKU를 결정할 수 있습니다.

최신 뉴스 및 리소스

다음 단계

정기 결제 관련 기능을 추가한 후 권장사항으로 진행하세요.