Ghid de Implementare a Achizițiilor în Aplicație

Ghid de Implementare a Achizițiilor în Aplicație

Bună. Sunt zm soft, care s-a înregistrat ca dezvoltator anul trecut (la sfârșitul lui 2023) și a început să lanseze aplicații. Plănuim să lansăm și o aplicație pentru dezvoltatori pentru a depăși testul închis împreună prin cooperare între dezvoltatori, așa că verificați dacă vă interesează.

Ați implementat cumpărături în aplicație? Pentru dezvoltatorii de aplicații, faptul că utilizatorii sunt mulțumiți și plătesc pentru asta este cel mai bun lucru, și este momentul în care efortul de dezvoltare este răsplătit. De data aceasta, vreau să scriu despre cum să realizez asta.

Ce Sunt Cumpărăturile în Aplicație

Cum știți deja, cumpărăturile în aplicație sunt clasificate în două tipuri:

  • Articole consumabile
  • Articole cu abonament periodic

Ambele adoptă abordarea de a accesa articolele configurate în prealabil în Play Store prin Google Play Billing Library, iar o parte din venitul obținut este plătită lui Google ca taxă. Din punct de vedere al implementării, ambele sunt similare, dar articolele cu abonament periodic au propriile lor avertismente. Voi explica avertismentele bazându-mă și pe experiența mea personală.

Configurarea Play Store

Înregistrarea Articolelor

Mai întâi, înregistrați articolele, deoarece nu pot fi afișate fără înregistrare. Prețul, numele etc., inclusiv dacă veți folosi cu adevărat acel articol, pot fi modificate ulterior, deci datele provizorii sunt în regulă. Cu toate acestea, doar ID-ul nu poate fi schimbat, deci dacă vă gândiți să utilizați articolele create pentru testare în producție după modificare, este mai bine să le înregistrați cu ID-uri reutilizabile precum [product_1,2,3...] sau [sub_1,2,3...]. Înregistrarea se poate face din [Monetize], unde [In-app products] și [Subscriptions] sunt, respectiv, articolele consumabile și cele cu abonament periodic. Fiecare articol poate fi înregistrat cu butonul [Create xx].

Play Console の Monetize メニューにあるアプリ内商品・定期購入セクション

În principiu, puteți urma ecranul de introducere, dar ceea ce a fost confuz a fost configurarea prețurilor pentru articolele cu abonament periodic. La început, nu știam cum să setez prețuri pentru toate regiunile dintr-o dată. Credeam că trebuie să introduc fiecare regiune individual, dar se poate face în ordinea: [Set prices] - [Country / region] - [Set price].

Play Console の定期購入価格入力フォーム

La apăsarea butonului, apare următorul dialog care permite configurarea dintr-o dată.

全地域一括価格設定ダイアログ(Play Console)

Înregistrarea Contului de Test

Apoi, înregistrați contul de test. Dacă efectuați un test de cumpărare fără să îl înregistrați, va apărea o plată reală, deci aveți grijă. Înregistrarea contului de test se face înregistrând o listă de e-mail. Înregistrarea poate fi făcută pe primul ecran (ecranul dezvoltatorului) după autentificarea în Play Console prin [Settings] - [License testing].

Play Console のライセンステスト設定画面(テストアカウント登録用)

Când efectuați procesul de cumpărare a aplicației cu un utilizator înregistrat în lista de e-mail, informațiile de plată vor fi afișate ca „card de test", permițând efectuarea testelor fără plată reală.

Lucrări de Implementare

Implementarea pe partea aplicației necesită următoarele lucrări:

  • Importarea bibliotecii
  • Conectarea la magazin și obținerea informațiilor despre articole
  • Implementarea ecranului de afișare a articolelor
  • Solicitarea cumpărăturii
  • Procesarea la finalizarea cumpărăturii

Mai jos voi descrie fiecare în detaliu.

Importarea Bibliotecii

Importarea bibliotecii necesită următoarele:

  • Modificarea build.gradle
  • Modificarea android.manifest

Exemplu de modificare build.gradle:

dependencies {
    implementation "com.android.billingclient:6.0.0"
}

Exemplu de modificare manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="com.android.vending.BILLING" />

    <application

Vă rugăm să consultați documentația oficială pentru versiune etc.

Conectarea la Magazin și Obținerea Informațiilor despre Articole

Inițializând BillingClient și rulând startConnection, comunicarea cu magazinul devine posibilă. Informațiile despre fiecare articol pot fi obținute cu queryProductDetailsAsync. Pentru detalii, consultați documentația oficială. În cazul meu, din anumite motive obținerea în bloc nu a funcționat bine, deci am obținut mai întâi lista de articole și apoi am obținut detaliile fiecărui articol individual cu queryProductDetailAsync. Articolul obținut (SKU) poate fi identificat ca consumabil sau cu abonament periodic din tipul său, inapp sau subs.

Implementarea Ecranului de Afișare a Articolelor

După obținerea informațiilor despre articole, afișați-le într-o listă pentru a putea selecta cumpărătura. Când gestionați articolele cu abonament periodic, este necesară conformarea cu Subscription Policy, iar în cazul meu, actualizările aplicației au fost respinse consecutiv din două motive:

  • Localizare incompletă a prețului și condițiilor
  • Descriere incompletă a condițiilor ofertei

Mai întâi, despre localizarea incompletă: motivul a fost afișarea perioadei (ex.: $10/month). Problema este că cuvântul "month" nu era tradus când rula cu setările de regiune ale unui limbaj nesuportat în traducere. Când obțineți informații cu BillingClient, suma prețului este recuperată ca string-ul formattedPrice care include informații despre unitate, deci nu este necesară traducerea în aplicație. Pe de altă parte, informațiile despre perioadă sunt notificate în format ISO 8601 ca P1M, iar acest lucru trebuie tradus în aplicație. Am tratat aceasta adăugând procese de conversie pentru fiecare limbă astfel:

fun formatBillingPeriod(billingPeriod: String, languageCode: String): String {
    return when(languageCode) {
        "en" -> {
            when (billingPeriod) {
                "P1W" -> "weekly"
                "P1M" -> "monthly"
                "P3M" -> "every 3 months"
                "P6M" -> "every 6 months"
                "P1Y" -> "annually"
                else -> "unknown"
            }
        }
        "ja" -> {
            when (billingPeriod) {
                "P1W" -> "週間"
                "P1M" -> "月額"
                "P3M" -> "3ヶ月ごと"
                "P6M" -> "6ヶ月ごと"
                "P1Y" -> "年額"
                else -> "不明"
            }
        }
        "fr" -> {
            when (billingPeriod) {
                "P1W" -> "hebdomadaire"
                "P1M" -> "mensuel"
                "P3M" -> "tous les 3 mois"
                "P6M" -> "tous les 6 mois"
                "P1Y" -> "annuel"
                else -> "inconnu"
            }
        }
        "es" -> {
            when (billingPeriod) {
                "P1W" -> "semanal"
                "P1M" -> "mensual"
                "P3M" -> "cada 3 meses"
                "P6M" -> "cada 6 meses"
                "P1Y" -> "anual"
                else -> "desconocido"
            }
        }
        "de" -> {
            when (billingPeriod) {
                "P1W" -> "wöchentlich"
                "P1M" -> "monatlich"
                "P3M" -> "alle 3 Monate"
                "P6M" -> "alle 6 Monate"
                "P1Y" -> "jährlich"
                else -> "unbekannt"
            }
        }
        else -> "unknown"
    }
}

Apoi, despre descrierea incompletă a condițiilor ofertei:

オファー条件違反のサブスクリプション拒否通知 サブスクリプションポリシー違反の拒否メール抜粋

Am înțeles problema, dar nu știam exact ce text concret să scriu ca soluție. Mai jos este un extras din textul original al e-mailului de respingere pe care l-am primit:

Issue found: Violation of Subscriptions policy

Your app does not comply with the Subscriptions policy.

  • Your offer does not clearly and accurately describe the terms of your trial offer or introductory pricing, including when a free trial will convert to a paid subscription, how much the paid subscription will cost, and that a user can cancel if they do not want to convert to a paid subscription.

Ca soluție, am împrumutat text din alte aplicații. Deoarece pare în mare parte text standard, am considerat că este mai bine să urmez precedente dovedite decât să mă gândesc de la zero.

Solicitarea Cumpărăturii

Odată ce utilizatorul poate selecta un articol din ecran, în cele din urmă vine procesarea cumpărăturii articolului. Executând fluxul de cumpărare pentru articolul obținut, ecranul real de cumpărare poate fi invocat.

Testare

Testarea poate fi efectuată fără a genera costuri reale autentificându-vă cu contul de test pregătit la început. Cele două puncte de atenție sunt:

  • Executarea fluxului de cumpărare se face cu aplicația înregistrată în magazin
  • Pentru articolele cu abonament periodic, perioada este setată personalizat

În ceea ce privește executarea fluxului de cumpărare, dacă aplicația este o versiune de depanare, va apărea o eroare pe ecranul de cumpărare și fluxul nu poate fi executat.

În ceea ce privește articolele cu abonament periodic, când avansați la ecranul real de cumpărare, se afișează plata cu cardul de test. În acel moment, pe ecranul de cumpărare este afișată perioada de reînnoire, dar această perioadă afișată este diferită de perioada configurată efectiv pentru articol. În cazul meu, erau afișate 5 minute. Se pare că este o specificație care afișează o perioadă fixă extrem de scurtă pentru comportamentul de reînnoire a abonamentului. (Am crezut că am configurat ceva greșit și am revizuit setările pentru o vreme.)

Concluzie

La început pare dificil, dar odată ce înțelegeți imaginea de ansamblu, cumpărăturile în aplicație în sine pot fi implementate surprinzător de ușor consultând informațiile disponibile public, cum ar fi documentația oficială. Cu toate acestea, pentru abonamentele periodice, există capcane pe care nu le poți descoperi decât dacă le încerci, deci sper că punctele în care am greșit să servească drept referință pentru dezvoltatorii care le vor implementa în viitor.