Hướng Dẫn Triển Khai Mua Hàng Trong Ứng Dụng

Hướng Dẫn Triển Khai Mua Hàng Trong Ứng Dụng

Xin chào. Tôi là zm soft, đã đăng ký làm nhà phát triển vào năm ngoái (cuối năm 2023) và bắt đầu phát hành ứng dụng. Chúng tôi cũng có kế hoạch phát hành ứng dụng dành cho nhà phát triển để cùng nhau vượt qua bài kiểm tra đóng thông qua sự hợp tác giữa các nhà phát triển, vì vậy hãy xem thử nếu bạn quan tâm.

Các bạn đã triển khai mua hàng trong ứng dụng chưa? Đối với các nhà phát triển ứng dụng, việc người dùng hài lòng và thanh toán cho điều đó là điều tuyệt vời nhất, và đó là khoảnh khắc nỗ lực phát triển được đền đáp. Lần này, tôi muốn viết về cách thực hiện điều đó.

Mua Hàng Trong Ứng Dụng Là Gì

Như các bạn đã biết, mua hàng trong ứng dụng được phân thành hai loại:

  • Mặt hàng tiêu thụ
  • Mặt hàng đăng ký định kỳ

Cả hai đều sử dụng cách tiếp cận truy cập các mặt hàng được cấu hình sẵn trong Play Store thông qua Google Play Billing Library, và một phần doanh thu thu được được trả cho Google làm phí. Về mặt triển khai, cả hai đều tương tự nhau, nhưng các mặt hàng đăng ký định kỳ có những lưu ý riêng. Tôi sẽ giải thích các lưu ý đó dựa trên kinh nghiệm thực tế của mình.

Cài Đặt Play Store

Đăng Ký Mặt Hàng

Trước tiên, hãy đăng ký các mặt hàng vì không thể hiển thị chúng nếu chưa đăng ký. Giá, tên, v.v., bao gồm cả việc có thực sự sử dụng mặt hàng đó hay không, đều có thể thay đổi sau, vì vậy dữ liệu tạm thời cũng được. Tuy nhiên, chỉ có ID là không thể thay đổi, vì vậy nếu bạn đang nghĩ đến việc sử dụng các mặt hàng được tạo để kiểm tra trong môi trường sản xuất sau khi sửa đổi, tốt hơn là đăng ký chúng với ID có thể tái sử dụng như [product_1,2,3...] hoặc [sub_1,2,3...]. Có thể đăng ký từ [Monetize], trong đó [In-app products] và [Subscriptions] lần lượt là mặt hàng tiêu thụ và mặt hàng đăng ký định kỳ. Mỗi mặt hàng có thể được đăng ký bằng nút [Create xx].

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

Về cơ bản, bạn có thể theo dõi màn hình nhập liệu, nhưng điều khiến tôi bối rối là cài đặt giá cho các mặt hàng đăng ký định kỳ. Lúc đầu, tôi không biết cách đặt giá cho tất cả các khu vực cùng một lúc. Tôi nghĩ phải nhập từng khu vực một, nhưng thực ra có thể làm theo thứ tự: [Set prices] - [Country / region] - [Set price].

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

Khi nhấn nút, hộp thoại sau xuất hiện và cho phép cài đặt tất cả cùng một lúc.

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

Đăng Ký Tài Khoản Test

Tiếp theo, đăng ký tài khoản test. Nếu bạn thực hiện mua hàng test mà không đăng ký, sẽ phát sinh thanh toán thực, vì vậy hãy chú ý. Đăng ký tài khoản test được thực hiện bằng cách đăng ký danh sách gửi thư. Có thể đăng ký trên màn hình đầu tiên (màn hình nhà phát triển) sau khi đăng nhập vào Play Console thông qua [Settings] - [License testing].

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

Khi thực hiện quá trình mua ứng dụng với người dùng được đăng ký trong danh sách gửi thư, thông tin thanh toán sẽ được hiển thị dưới dạng "thẻ test", cho phép thực hiện kiểm tra mà không có thanh toán thực.

Công Việc Triển Khai

Triển khai phía ứng dụng cần thực hiện các công việc sau:

  • Nhập thư viện
  • Kết nối với cửa hàng và lấy thông tin mặt hàng
  • Triển khai màn hình hiển thị mặt hàng
  • Yêu cầu mua hàng
  • Xử lý khi hoàn thành mua hàng

Dưới đây tôi sẽ mô tả chi tiết từng phần.

Nhập Thư Viện

Nhập thư viện cần những điều sau:

  • Sửa đổi build.gradle
  • Sửa đổi android.manifest

Ví dụ sửa đổi build.gradle:

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

Ví dụ sửa đổi 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

Vui lòng kiểm tra tài liệu chính thức về phiên bản v.v.

Kết Nối với Cửa Hàng và Lấy Thông Tin Mặt Hàng

Bằng cách khởi tạo BillingClient và chạy startConnection, việc giao tiếp với cửa hàng trở nên khả thi. Thông tin của từng mặt hàng có thể lấy bằng queryProductDetailsAsync. Để biết chi tiết, vui lòng kiểm tra tài liệu chính thức. Trong trường hợp của tôi, vì lý do nào đó việc lấy hàng loạt không hoạt động tốt, vì vậy tôi đã lấy danh sách mặt hàng trước rồi lấy chi tiết từng mặt hàng riêng lẻ bằng queryProductDetailAsync. Mặt hàng thu được (SKU) có thể được phân biệt là tiêu thụ hay đăng ký định kỳ từ loại của nó, inapp hay subs.

Triển Khai Màn Hình Hiển Thị Mặt Hàng

Sau khi lấy được thông tin mặt hàng, hiển thị chúng dưới dạng danh sách để có thể chọn mua hàng. Khi xử lý các mặt hàng đăng ký định kỳ ở đây, cần tuân thủ Subscription Policy, và trong trường hợp của tôi, các bản cập nhật ứng dụng liên tục bị từ chối vì hai lý do sau:

  • Bản địa hóa không đầy đủ về giá và điều kiện
  • Mô tả không đầy đủ về điều kiện ưu đãi

Đầu tiên, về bản địa hóa không đầy đủ: lý do là việc hiển thị kỳ hạn (ví dụ: $10/month). Vấn đề là từ "month" không được dịch khi chạy với cài đặt khu vực của ngôn ngữ không được hỗ trợ dịch. Khi lấy thông tin bằng BillingClient, số tiền giá được lấy dưới dạng chuỗi formattedPrice bao gồm thông tin đơn vị, vì vậy không cần dịch trong ứng dụng. Mặt khác, thông tin kỳ hạn được thông báo ở định dạng ISO 8601 như P1M, và cần phải dịch trong ứng dụng. Tôi xử lý bằng cách thêm các quy trình chuyển đổi cho từng ngôn ngữ như sau:

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"
    }
}

Tiếp theo, về mô tả không đầy đủ về điều kiện ưu đãi:

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

Tôi hiểu vấn đề, nhưng không biết cụ thể phải viết từ ngữ nào để giải quyết. Dưới đây là trích đoạn từ văn bản gốc của email từ chối tôi nhận được:

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.

Là giải pháp, tôi đã mượn ngôn ngữ từ các ứng dụng khác. Vì đây phần lớn có vẻ là ngôn ngữ tiêu chuẩn, tôi nghĩ tốt hơn là nên theo các tiền lệ đã được chứng minh hơn là tự nghĩ ra từ đầu.

Yêu Cầu Mua Hàng

Sau khi người dùng có thể chọn mặt hàng từ màn hình, cuối cùng đến phần xử lý mua hàng. Bằng cách thực thi luồng mua hàng cho mặt hàng đã lấy được, có thể gọi màn hình mua hàng thực sự.

Kiểm Tra

Có thể thực hiện kiểm tra mà không phát sinh phí thực tế bằng cách đăng nhập bằng tài khoản test đã chuẩn bị từ đầu. Hai điểm cần lưu ý ở đây là:

  • Thực thi luồng mua hàng được thực hiện với ứng dụng đã đăng ký trên cửa hàng
  • Đối với mặt hàng đăng ký định kỳ, kỳ hạn được cài đặt tùy chỉnh

Về thực thi luồng mua hàng: nếu ứng dụng là debug build, sẽ có lỗi hiển thị trên màn hình mua hàng và không thể thực thi luồng.

Về các mặt hàng đăng ký định kỳ: khi tiến đến màn hình mua hàng thực tế, hiển thị thanh toán bằng thẻ test. Lúc này, kỳ hạn gia hạn được hiển thị trên màn hình mua hàng, nhưng kỳ hạn được hiển thị này khác với kỳ hạn thực sự được cấu hình cho mặt hàng. Trong trường hợp của tôi, hiển thị 5 phút. Có vẻ đây là thông số kỹ thuật hiển thị kỳ hạn cố định cực ngắn cho hành vi gia hạn đăng ký. (Tôi nghĩ mình đã cài đặt sai gì đó và đã xem xét lại cài đặt một lúc.)

Tóm Tắt

Lúc đầu có vẻ khó, nhưng sau khi hiểu được bức tranh tổng thể, bản thân việc mua hàng trong ứng dụng có thể được triển khai một cách dễ dàng đáng ngạc nhiên bằng cách xem thông tin công khai như tài liệu chính thức. Tuy nhiên, đối với các đăng ký định kỳ, có những bẫy chỉ có thể phát hiện khi thử, vì vậy tôi hy vọng những điểm mà tôi đã vấp ngã sẽ là tài liệu tham khảo cho các nhà phát triển sẽ triển khai nó trong tương lai.