Play Faturalandırma'da ürün satın alma işlemlerindeki düşüşleri analiz etme

1. Giriş

Bu codelab'de tek seferlik ürün oluşturmaya, uygulamanızı Play Faturalandırma Kitaplığı (PBL) ile entegre etmeye ve satın alma işlemlerindeki düşüşlerin nedenlerini analiz etmeye odaklanacaksınız.

Kitle

Bu codelab, Play Faturalandırma Kitaplığı'nı (PBL) kullanan veya tek seferlik ürünlerinden para kazanmak için PBL'yi kullanmak isteyen Android uygulaması geliştiricilerine yöneliktir.

Öğrenecekleriniz...

  • Google Play Console'da tek seferlik ürün oluşturma
  • Uygulamanızı PBL ile entegre etme
  • PBL'de tüketilebilir ve tüketilemez tek seferlik ürün satın alma işlemlerini işleme
  • Satın alma sürecindeki düşüşleri analiz etme

İhtiyacınız olanlar...

2. Örnek uygulamayı oluşturma

Örnek uygulama, aşağıdaki yönleri gösteren eksiksiz kaynak koduna sahip, tamamen işlevsel bir Android uygulaması olacak şekilde tasarlanmıştır:

  • Uygulamayı PBL ile entegre etme
  • Tek seferlik ürünleri getirme
  • Tek seferlik ürünler için satın alma akışlarını başlatın
  • Aşağıdaki faturalandırma yanıtlarına yol açan satın alma senaryoları:
    • BILLING_UNAVAILABLE
    • USER_CANCELLED
    • OK
    • ITEM_ALREADY_OWNED

Aşağıdaki demo videosunda, örnek uygulamanın dağıtılıp çalıştırıldıktan sonra nasıl görüneceği ve davranacağı gösterilmektedir.

Ön koşullar

Örnek uygulamayı oluşturup dağıtmadan önce aşağıdakileri yapın:

Derleme

Bu derleme adımının amacı, örnek uygulamanın imzalı bir Android App Bundle dosyasını oluşturmaktır.

Android uygulama paketini oluşturmak için aşağıdaki adımları uygulayın:

  1. GitHub'dan örnek uygulamayı indirin.
  2. Örnek uygulamayı oluşturun. Oluşturmadan önce örnek uygulamanın paket adını değiştirin ve ardından oluşturun. Play Console'da başka uygulamaların paketleri varsa örnek uygulama için sağladığınız paket adının benzersiz olduğundan emin olun.

    Not: Örnek uygulamayı oluşturduğunuzda yalnızca yerel test için kullanabileceğiniz bir APK dosyası oluşturulur. Ancak, uygulama çalıştırıldığında ürünler ve fiyatlar getirilmez. Bunun nedeni, ürünlerin Play Console'da yapılandırılmamış olmasıdır. Bu yapılandırmayı bu codelab'in ilerleyen bölümlerinde yapacaksınız.
  3. İmzalı bir Android App Bundle oluşturun.
    1. Yükleme anahtarı ve anahtar deposu oluşturma
    2. Uygulamanızı yükleme anahtarınızla imzalama
    3. Play Uygulama İmzalama'yı yapılandırma

Bir sonraki adım, Android uygulama paketini Google Play Console'a yüklemektir.

3. Play Console'da tek seferlik ürün oluşturma

Google Play Console'da tek seferlik ürünler oluşturmak için Play Console'da bir uygulamanızın olması gerekir. Play Console'da bir uygulama oluşturun ve daha önce oluşturulan imzalı uygulama paketini yükleyin.

Uygulama oluşturma

Uygulama oluşturmak için:

  1. Geliştirici hesabınızı kullanarak Google Play Console'da oturum açın.
  2. Uygulama oluştur'u tıklayın. Uygulama oluştur sayfası açılır.
  3. Uygulama adını girin, varsayılan dili ve uygulamayla ilgili diğer ayrıntıları seçin.
  4. Uygulama oluştur'u tıklayın. Bu işlem, Google Play Console'da bir uygulama oluşturur.

Artık örnek uygulamanın imzalı uygulama paketini yükleyebilirsiniz.

İmzalı uygulama paketini yükleyin

  1. İmzalı uygulama paketini Google Play Console'un dahili test kanalına yükleyin. Para kazanmayla ilgili özellikleri Play Console'da yalnızca yükleme işleminden sonra yapılandırabilirsiniz.
  2. Test edin ve yayınlayın > Test > Dahili sürüm > Yeni sürüm oluştur'u tıklayın.
  3. Bir sürüm adı girin ve imzalı uygulama paketi dosyasını yükleyin.
  4. Sonraki'yi ve ardından Kaydet ve yayınla'yı tıklayın.

Artık tek seferlik ürünlerinizi oluşturabilirsiniz.

Tek seferlik ürün oluşturma

Tek seferlik ürün oluşturmak için:

  1. Google Play Console'da soldaki gezinme menüsünden Google Play ile para kazanın > Ürünler > Tek seferlik ürünler'e gidin.
  2. Tek seferlik ürün oluştur'u tıklayın.
  3. Aşağıdaki ürün ayrıntılarını girin:
    • Ürün kimliği: Benzersiz bir ürün kimliği girin. one_time_product_01 yazın.
    • (İsteğe bağlı) Etiketler: Alakalı etiketler ekleyin.
    • Ad: Ürün adı girin. Örneğin, Product name.
    • Açıklama: Ürün açıklaması girin. Örneğin, Product description.
    • (İsteğe bağlı) Simge görseli ekleyin: Ürününüzü temsil eden bir simge yükleyin.
    Not: Bu codelab'in amacı doğrultusunda Vergi, kanunlara ve kurallara uygunluk, programlar bölümünü yapılandırmayı atlayabilirsiniz.
  4. İleri'yi tıklayın.
  5. Satın alma seçeneği ekleyin ve bölgesel kullanılabilirliğini yapılandırın. Tek seferlik ürünler için en az bir satın alma seçeneği gerekir. Bu seçenek, yetkinin nasıl verileceğini, fiyatını ve bölgesel stok durumunu tanımlar. Bu codelab'de ürün için standart Satın al seçeneğini ekleyeceğiz.Satın alma seçeneği bölümünde aşağıdaki ayrıntıları girin:
    • Satın alma seçeneği kimliği: Satın alma seçeneği kimliği girin. Örneğin, buy.
    • Satın alma türü: Satın al'ı seçin.
    • (İsteğe bağlı) Etiketler: Bu satın alma seçeneğine özel etiketler ekleyin.
    • (İsteğe bağlı) Gelişmiş seçenekleri yapılandırmak için Gelişmiş seçenekler'i tıklayın. Bu codelab'in amacı doğrultusunda gelişmiş seçenekler yapılandırmasını atlayabilirsiniz.
  6. Stok durumu ve fiyatlandırma bölümünde Fiyatları ayarla > Fiyatlandırmayı toplu olarak düzenle'yi tıklayın.
  7. Ülke / bölge seçeneğini belirleyin. Bu işlem tüm bölgeleri seçer.
  8. Devam'ı tıklayın. Fiyat girmeniz için bir iletişim kutusu açılır. 10 ABD doları girip Uygula'yı tıklayın.
  9. Kaydet'i ve ardından Etkinleştir'i tıklayın. Bu işlem, satın alma seçeneğini oluşturup etkinleştirir.

Bu codelab'de kullanmak üzere aşağıdaki ürün kimliklerine sahip 3 ek tek seferlik ürün oluşturun:

  • consumable_product_01
  • consumable_product_02
  • consumable_product_03

Örnek uygulama, bu ürün kimliklerini kullanacak şekilde yapılandırılmıştır. Farklı ürün kimlikleri sağlayabilirsiniz. Bu durumda, sağladığınız ürün kimliğini kullanmak için örnek uygulamayı değiştirmeniz gerekir.

Google Play Console'da örnek uygulamayı açın ve Play ile para kazanma > Ürünler > Tek seferlik ürünler'e gidin. Ardından Tek seferlik ürün oluştur'u tıklayın ve 3-9 arasındaki adımları tekrarlayın.

Tek seferlik ürün oluşturma videosu

Aşağıdaki örnek videoda, daha önce açıklanan tek seferlik ürün oluşturma adımları gösterilmektedir.

4. PBL ile entegrasyon

Şimdi uygulamanızı Play Faturalandırma Kitaplığı (PBL) ile nasıl entegre edeceğinizi göreceğiz. Bu bölümde, entegrasyonla ilgili üst düzey adımlar açıklanmakta ve her adım için bir kod snippet'i sağlanmaktadır. Bu snippet'leri, gerçek entegrasyonunuzu uygularken yol gösterici olarak kullanabilirsiniz.

Uygulamanızı PBL ile entegre etmek için aşağıdaki adımları uygulayın:

  1. Örnek uygulamaya Play Faturalandırma Kitaplığı bağımlılığını ekleyin.
    dependencies {
    val billing_version = "8.0.0"
    
    implementation("com.android.billingclient:billing-ktx:$billing_version")
    }
    
  2. BillingClient'ı başlatın. BillingClient, uygulamanızda bulunan ve Play Faturalandırma Kitaplığı ile iletişim kuran istemci SDK'sıdır. Aşağıdaki kod snippet'inde faturalandırma istemcisinin nasıl başlatılacağı gösterilmektedir.
    protected BillingClient createBillingClient() {
    return BillingClient.newBuilder(activity)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
        .enableAutoServiceReconnection()
        .build();
    }
    
  3. Google Play'e bağlanın.Aşağıdaki kod snippet'inde Google Play'e nasıl bağlanılacağı gösterilmektedir.
    public void startBillingConnection(ImmutableList<Product> productList) {
    Log.i(TAG, "Product list sent: " + productList);
    Log.i(TAG, "Starting connection");
    billingClient.startConnection(
        new BillingClientStateListener() {
          @Override
          public void onBillingSetupFinished(BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
              // Query product details to get the product details list.
              queryProductDetails(productList);
            } else {
              // BillingClient.enableAutoServiceReconnection() will retry the connection on
              // transient errors automatically.
              // We don't need to retry on terminal errors (e.g., BILLING_UNAVAILABLE,
              // DEVELOPER_ERROR).
              Log.e(TAG, "Billing connection failed: " + billingResult.getDebugMessage());
              Log.e(TAG, "Billing response code: " + billingResult.getResponseCode());
            }
          }
    
          @Override
          public void onBillingServiceDisconnected() {
            Log.e(TAG, "Billing Service connection lost.");
          }
        });
    }
    
  4. Tek seferlik ürün ayrıntılarını getirin.Uygulamanızı PBL ile entegre ettikten sonra tek seferlik ürün ayrıntılarını uygulamanıza getirmeniz gerekir. Aşağıdaki kod snippet'i, tek seferlik ürün ayrıntılarını uygulamanıza nasıl getireceğinizi gösterir.
    private void queryProductDetails(ImmutableList<Product> productList) {
    Log.i(TAG, "Querying products for: " + productList);
    QueryProductDetailsParams queryProductDetailsParams =
        QueryProductDetailsParams.newBuilder().setProductList(productList).build();
    billingClient.queryProductDetailsAsync(
        queryProductDetailsParams,
        new ProductDetailsResponseListener() {
          @Override
          public void onProductDetailsResponse(
              BillingResult billingResult, QueryProductDetailsResult productDetailsResponse) {
            // check billingResult
            Log.i(TAG, "Billing result after querying: " + billingResult.getResponseCode());
            // process returned productDetailsList
            Log.i(
                TAG,
                "Print unfetched products: " + productDetailsResponse.getUnfetchedProductList());
            setupProductDetailsMap(productDetailsResponse.getProductDetailsList());
            billingServiceClientListener.onProductDetailsFetched(productDetailsMap);
          }
        });
    }
    
    ProductDetails getirme işlemi, aşağıdakine benzer bir yanıt verir:
    {
        "productId": "consumable_product_01",
        "type": "inapp",
        "title": "Shadow Coat (Yolo's Realm | Play Samples)",
        "name": "Shadow Coat",
        "description": "A sleek, obsidian coat for stealth and ambushes",
        "skuDetailsToken": "<---skuDetailsToken--->",
        "oneTimePurchaseOfferDetails": {},
        "oneTimePurchaseOfferDetailsList": [
            {
                "priceAmountMicros": 1990000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$1.99",
                "offerIdToken": "<--offerIdToken-->",
                "purchaseOptionId": "buy",
                "offerTags": []
            }
        ]
    },
    {
        "productId": "consumable_product_02",
        "type": "inapp",
        "title": "Emperor Den (Yolo's Realm | Play Samples)",
        "name": "Emperor Den",
        "description": "A fair lair glowing with molten rock and embers",
        "skuDetailsToken": "<---skuDetailsToken--->",
        "oneTimePurchaseOfferDetails": {},
        "oneTimePurchaseOfferDetailsList": [
            {
                "priceAmountMicros": 2990000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$2.99",
                "offerIdToken": "<--offerIdToken-->",
                "purchaseOptionId": "buy",
                "offerTags": []
            }
        ]
    }
    
  5. Faturalandırma akışını başlatın.
    public void launchBillingFlow(String productId) {
    ProductDetails productDetails = productDetailsMap.get(productId);
    if (productDetails == null) {
      Log.e(
          TAG, "Cannot launch billing flow: ProductDetails not found for productId: " + productId);
      billingServiceClientListener.onBillingResponse(
          BillingResponseCode.ITEM_UNAVAILABLE,
          BillingResult.newBuilder().setResponseCode(BillingResponseCode.ITEM_UNAVAILABLE).build());
      return;
    }
    ImmutableList<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
            ProductDetailsParams.newBuilder().setProductDetails(productDetails).build());
    
    BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .build();
    
    billingClient.launchBillingFlow(activity, billingFlowParams);
    }
    
  6. Satın alma işlemlerini algılayıp işleme. Bu adımda yapmanız gerekenler:
    1. Satın alma işlemini doğrulama
    2. Kullanıcıya yararlanma hakkı verme
    3. Kullanıcıyı bilgilendirme
    4. Satın alma süreci hakkında Google'ı bilgilendirme
    Bunlardan a, b ve c adımları arka uçta yapılmalıdır ve bu nedenle bu kod laboratuvarının kapsamı dışındadır.Aşağıdaki snippet, tek seferlik tüketilebilir bir ürün için Google'a nasıl bildirim gönderileceğini gösterir:
    private void handlePurchase(Purchase purchase) {
    // Step 1: Send the purchase to your secure backend to verify the purchase following
    // https://developer.android.com/google/play/billing/security#verify
    
    // Step 2: Update your entitlement storage with the purchase. If purchase is
    // in PENDING state then ensure the entitlement is marked as pending and the
    // user does not receive benefits yet. It is recommended that this step is
    // done on your secure backend and can combine in the API call to your
    // backend in step 1.
    
    // Step 3: Notify the user using appropriate messaging.
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
      for (String product : purchase.getProducts()) {
        Log.d(TAG, product + " purchased successfully! ");
      }
    }
    
    // Step 4: Notify Google the purchase was processed.
    // For one-time products, acknowledge the purchase.
    // This sample app (client-only) uses billingClient.acknowledgePurchase().
    // For consumable one-time products, consume the purchase
    // This sample app (client-only) uses billingClient.consumeAsync()
    // If you have a secure backend, you must acknowledge purchases on your server using the
    // server-side API.
    // See https://developer.android.com/google/play/billing/security#acknowledge
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED && !purchase.isAcknowledged()) {
    
      if (shouldConsume(purchase)) {
        ConsumeParams consumeParams =
            ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
        billingClient.consumeAsync(consumeParams, consumeResponseListener);
    
      } else {
        AcknowledgePurchaseParams acknowledgePurchaseParams =
            AcknowledgePurchaseParams.newBuilder()
                .setPurchaseToken(purchase.getPurchaseToken())
                .build();
        billingClient.acknowledgePurchase(
            acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
      }
     }
    }
    

5. Satın alma sürecindeki bırakmaları analiz etme

Bu codelab'de şu ana kadar Play Faturalandırma yanıtları USER_CANCELLED, BILLING_UNAVAILABLE, OK ve ITEM_ALREADY_OWNED gibi yanıtlar gibi sınırlı senaryolara odaklandı. Ancak Play Faturalandırma, çeşitli gerçek dünya faktörleri tarafından tetiklenebilen 13 farklı yanıt kodu döndürebilir.

Bu bölümde, USER_CANCELLED ve BILLING_UNAVAILABLE hata yanıtlarının nedenleri ayrıntılı olarak açıklanmakta ve uygulayabileceğiniz olası düzeltici işlemler önerilmektedir.

USER_CANCELED yanıt hata kodu

Bu yanıt kodu, kullanıcının satın alma işlemini tamamlamadan önce satın alma akışı kullanıcı arayüzünden çıktığını gösterir.

Olası nedenler

Hangi işlemleri yapabilirsiniz?

  • Fiyatlara duyarlı olan ve satın alma niyeti düşük kullanıcıları gösterebilir.
  • Satın alma işlemi beklemede veya ödeme reddedildi.

BILLING_UNAVAILABLE yanıt hata kodu

Bu yanıt kodu, kullanıcının ödeme sağlayıcısı veya seçtiği ödeme şekliyle ilgili bir sorun nedeniyle satın alma işleminin tamamlanamadığı anlamına gelir. Örneğin, kullanıcının kredi kartının süresi dolmuş veya kullanıcı, desteklenmeyen bir ülkede bulunuyor. Bu kod, Play Faturalandırma sisteminin kendisiyle ilgili bir hatayı göstermez.

Olası nedenler

Hangi işlemleri yapabilirsiniz?

  • Kullanıcının cihazındaki Play Store uygulaması güncel değildir.
  • Kullanıcı, Play'in desteklenmediği bir ülkede bulunuyor.
  • Kullanıcı bir kurumsal kullanıcıdır ve kurumsal yöneticisi, kullanıcıların satın alma işlemi yapmasını devre dışı bırakmıştır.
  • Google Play, kullanıcının ödeme yönteminden ödeme alamıyor. Örneğin, kullanıcının kredi kartının geçerlilik süresi dolmuş olabilir.
  • Sistem sorunları ve belirli bölgelerdeki trendleri izleme
  • PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS alt yanıt kodunu desteklediği için PBL 8'e geçmeyi düşünebilirsiniz. Bu yanıt kodunu alırsanız kullanıcıları hatayla ilgili olarak bilgilendirmeyi veya alternatif ödeme yöntemleri önermeyi düşünebilirsiniz.
  • Bu yanıt kodu, uygun yeniden deneme stratejileri uygulamanıza olanak tanıyarak yeniden denemeler için tasarlanmıştır.
    Bu durumda otomatik yeniden denemelerin yardımcı olması beklenmez. Ancak kullanıcı, soruna neden olan koşulu düzeltirse manuel olarak yeniden deneme işlemi yardımcı olabilir. Örneğin, kullanıcı Play Store sürümünü desteklenen bir sürüme güncellerse ilk işlemin manuel olarak yeniden denenmesi işe yarayabilir.

    Kullanıcı oturumda değilken bu yanıt kodunu alırsanız yeniden denemek mantıklı olmayabilir. Satın alma akışı sonucunda "BILLING_UNAVAILABLE" yanıtı aldığınızda, kullanıcının satın alma işlemi sırasında Google Play'den geri bildirim alması ve neyin yanlış gittiğinin farkında olması çok olasıdır. Bu durumda, bir hata oluştuğunu belirten bir hata mesajı gösterebilir ve kullanıcıya sorunu çözdükten sonra manuel olarak tekrar deneme seçeneği sunmak için "Tekrar dene" düğmesi ekleyebilirsiniz.

Yanıt hata kodları için yeniden deneme stratejileri

Play Faturalandırma Kitaplığı'ndaki (PBL) kurtarılabilir hatalar için etkili yeniden deneme stratejileri, oturumdaki kullanıcı etkileşimleri (ör. satın alma işlemi sırasında) ile arka plan işlemleri (ör. uygulama devam ettirildiğinde satın alma işlemlerini sorgulama) gibi bağlama göre değişir. Bu stratejileri uygulamak önemlidir. Çünkü belirli BillingResponseCode değerleri, yeniden denemeyle çözülebilecek geçici sorunları ifade ederken diğerleri kalıcıdır ve yeniden deneme gerektirmez.

Kullanıcı oturumdayken karşılaşılan hatalar için kullanıcı deneyimindeki kesintiyi en aza indirmek amacıyla belirli bir maksimum deneme sayısına sahip basit bir yeniden deneme stratejisi kullanılması önerilir. Buna karşılık, yeni satın alma işlemlerini onaylama gibi hemen yürütülmesini gerektirmeyen arka plan işlemleri için üstel geri çekilme yaklaşımı önerilir.

Belirli yanıt kodları ve bunlara karşılık gelen önerilen yeniden deneme stratejileri hakkında ayrıntılı bilgi için BillingResult yanıt kodlarını işleme başlıklı makaleyi inceleyin.

6. Sonraki adımlar

Referans belgeleri

7. Tebrikler!

Tebrikler! Google Play Console'da başarılı bir şekilde gezinerek yeni bir tek seferlik ürün oluşturdunuz, faturalandırma yanıt kodlarını test ettiniz ve satın alma işlemlerindeki düşüşleri analiz ettiniz.

Anket

Bu codelab ile ilgili geri bildiriminiz bizim için çok değerli. Anketimizi tamamlamak için birkaç dakikanızı ayırabilirsiniz.