メインコンテンツまでスキップ

Google Play Billing 移行用 AI プロンプト

概要

この AI プロンプトは、大規模言語モデル(ChatGPT、Claude、Gemini など)を駆動して、Google Play Billing のコードを Aptoide Android Billing SDK へ移行します。既存の統合と併せて貼り付けると、AI が移行エンジニアとして動作し、ビルドフレーバーをセットアップし、Aptoide 固有の API を使用して現在のプロジェクトのアーキテクチャパターンを反映します。


AI プロンプト

## PROMPT: Adaptive Mirror-Integration of Aptoide Billing SDK

## Goal
Integrate the Aptoide Billing SDK into this Android project by strictly mirroring the existing Google Play Billing implementation. The objective is to have a "plug-and-play" version for Aptoide that follows the current project's coding patterns, naming conventions, and architecture, but uses the correct Aptoide-specific APIs.

## Reference Documentation
Use this for Aptoide-specific syntax: https://docs.connect.aptoide.com/docs/android-billing-sdk

## Step 1: Analysis of Current Implementation
1. Scan the project to identify how **Google Play Billing** is currently implemented.
2. Identify the key components:
* Where the Google `BillingClient` is initialized.
* Which wrapper classes (e.g., `BillingManager`, `BillingRepository`) handle the purchase flow, SKU/Product queries, and consumption.
* How the UI or ViewModels observe purchase updates (e.g., Listeners, LiveData, Flows).
* How Dependency Injection (if any) provides the Billing service.

## Step 2: Infrastructure Setup (Build Variants)
1. Define a `distribution` flavor dimension in the app-level `build.gradle` (or `build.gradle.kts`).
2. Create two flavors: `googlePlay` and `aptoide`.
3. Isolate dependencies:
* Move Google Billing dependencies to `googlePlayImplementation`.
* Add Aptoide Billing to `aptoideImplementation` using the `+` to always have the newest version of major available: `implementation("com.aptoide:android-aptoide-billing:1.+")`.
4. In a multi-modular project, add correctly the flavor dimensions to all the `build.gradle` files that use the Billing module.

## Step 3: Aptoide Public Key Configuration (CRITICAL)
1. In the root `gradle.properties` file, add a placeholder variable: `APTOIDE_PUBLIC_KEY="PASTE_YOUR_PUBLIC_KEY_HERE"`
2. In the app-level `build.gradle` `aptoide` flavor block, expose this to the app using `buildConfigField`:
* Groovy: `buildConfigField "String", "APTOIDE_PUBLIC_KEY", project.property('APTOIDE_PUBLIC_KEY')`
* Kotlin DSL: `buildConfigField("String", "APTOIDE_PUBLIC_KEY", project.property("APTOIDE_PUBLIC_KEY").toString())`
3. **Developer Note requirement:** In your final response to me, display a prominent warning reminding me to replace the placeholder in `gradle.properties` with the actual key from the Aptoide Console.

## Step 4: Mirror-Image Implementation (Source Sets)
1. **Source Set Separation:**
* Move the existing Google Billing wrapper logic/classes into `src/googlePlay/java` (or `kotlin`).
* Create identical class files and package structures in `src/aptoide/java` (or `kotlin`).
2. **Wrapper Class Parity:**
* Inside `src/aptoide/`, rewrite the billing wrapper logic using the Aptoide SDK. You MUST keep the **exact same wrapper class names, custom method signatures, and custom return types** as the Google version (e.g., if Google has `class MyBillingManager`, Aptoide must have `class MyBillingManager`).
3. **Aptoide SDK Specifics (DO NOT USE GOOGLE IMPORTS IN APTOIDE):**
* Use Aptoide imports: `com.aptoide.sdk.billing.*` (e.g., `AptoideBillingClient`, `Purchase`, `ProductDetails`, `BillingFlowParams`, `QueryProductDetailsParams`) and `com.aptoide.sdk.billing.listeners.*` for the listeners (e.g., `AptoideBillingClientStateListener`, `ConsumeResponseListener`). Here is a list of all the available classes, annotations and listeners in Aptoide Billing SDK:
- com.aptoide.sdk.billing.AptoideBillingClient.BillingResponseCode
- com.aptoide.sdk.billing.AptoideBillingClient.FeatureType
- com.aptoide.sdk.billing.AptoideBillingClient.ProductType
- com.aptoide.sdk.billing.UnfetchedProduct.StatusCode
- com.aptoide.sdk.billing.AccountIdentifiers
- com.aptoide.sdk.billing.AptoideBillingClient
- com.aptoide.sdk.billing.BillingFlowParams
- com.aptoide.sdk.billing.BillingFlowParams.Builder
- com.aptoide.sdk.billing.BillingFlowParams.ProductDetailsParams
- com.aptoide.sdk.billing.BillingFlowParams.ProductDetailsParams.Builder
- com.aptoide.sdk.billing.BillingResult
- com.aptoide.sdk.billing.ConsumeParams
- com.aptoide.sdk.billing.ConsumeParams.Builder
- com.aptoide.sdk.billing.ProductDetails
- com.aptoide.sdk.billing.ProductDetails.OneTimePurchaseOfferDetails
- com.aptoide.sdk.billing.ProductDetails.PricingPhase
- com.aptoide.sdk.billing.ProductDetails.PricingPhases
- com.aptoide.sdk.billing.ProductDetails.SubscriptionOfferDetails
- com.aptoide.sdk.billing.ProductDetails.TrialDetails
- com.aptoide.sdk.billing.Purchase
- com.aptoide.sdk.billing.QueryProductDetailsParams
- com.aptoide.sdk.billing.QueryProductDetailsParams.Builder
- com.aptoide.sdk.billing.QueryProductDetailsParams.Product
- com.aptoide.sdk.billing.QueryProductDetailsParams.Product.Builder
- com.aptoide.sdk.billing.QueryProductDetailsResult
- com.aptoide.sdk.billing.QueryPurchasesParams
- com.aptoide.sdk.billing.QueryPurchasesParams.Builder
- com.aptoide.sdk.billing.ReferralDeeplink
- com.aptoide.sdk.billing.UnfetchedProduct
- com.aptoide.sdk.billing.listeners.AptoideBillingClientStateListener
- com.aptoide.sdk.billing.listeners.ConsumeResponseListener
- com.aptoide.sdk.billing.ProductDetailsResponseListener
- com.aptoide.sdk.billing.PurchasesResponseListener
- com.aptoide.sdk.billing.PurchasesUpdatedListener
* **Initialization:** You MUST replace `BillingClient` with `AptoideBillingClient`. It requires the Public Key in the Builder. Use exactly this pattern:
```kotlin
val billingClient = AptoideBillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.setPublicKey(BuildConfig.APTOIDE_PUBLIC_KEY)
.build()
```
* Use `AptoideBillingClientStateListener` for the `startConnection` method.

## Step 5: Semantic Feature Mapping (SDK Differences)
Identify and bridge the functional gaps between the two SDKs to maintain signature parity:

1. **Threading differences (CRITICAL):** The Aptoide `launchBillingFlow()` method **MUST NOT** be called on the Main/UI Thread (this will cause a crash). Wrap the `launchBillingFlow()` call inside a background thread (e.g., Coroutines `Dispatchers.IO` or an RxJava background scheduler) in the Aptoide implementation.
2. **Acknowledge vs Consume:** Aptoide does not support a separate `acknowledgePurchase` step like Google does for subscriptions/non-consumables. If the Google implementation has an `acknowledge()` method, implement it as a "No-Op" (returning success immediately) in the Aptoide flavor, and ensure all purchases are finalized using Aptoide's `consumeAsync` function instead.
3. **Product Types:** Map Google’s `ProductType.SUBS` and `ProductType.INAPP` to `AptoideBillingClient.ProductType.SUBS` and `AptoideBillingClient.ProductType.INAPP`.
4. **General Logic:** Verify all other functional differences and apply the Aptoide SDK logic correctly while maintaining the original custom wrapper method signatures so the UI doesn't break.

## Step 6: Verification & Cleanliness
* The `src/main` folder should remain completely untouched.
* The UI and ViewModels should not know which SDK is being used; they should simply call the wrapper classes that now exist in both flavor source sets.

---

## PHASE 2: Validation Audit (Mandatory)

After completing the code generation, you must perform a self-audit and report on the following:

1. **Isolation Audit:** Confirm zero `com.aptoide.sdk.billing` imports exist in `src/main` or `src/googlePlay`. Conversely, confirm zero `com.android.billingclient.api` imports exist in `src/aptoide`.
2. **Threading Audit:** Explicitly verify that `AptoideBillingClient.launchBillingFlow()` is executed on a background thread.
3. **Builder Audit:** Explicitly verify that `AptoideBillingClient.newBuilder` uses `.setPublicKey(BuildConfig.APTOIDE_PUBLIC_KEY)`.
4. **Signature Check:** Confirm that the public API of your custom wrapper classes in `src/aptoide` is identical to the `src/googlePlay` version.
5. **Cleanliness Check:** Confirm that `src/main` (UI/ViewModels) remained untouched.

**Final Requirement:** If any discrepancies are found during your audit, fix them before providing the final code and report.

このプロンプトの使用方法

このプロンプトを Web ベースの AI(ChatGPT や Claude など)にコピー&ペーストすることもできますが、リポジトリのコンテキストを直接持つ AI 搭載 IDE またはエージェントを使用することで、最も高い成功率を達成できます。

推奨されるアプローチ: AI コードエディター(Cursor / Android Studio 統合 AI)

CursorAndroid Studio 内蔵の統合 AI エージェントのようなツールを使用すると、AI がコードベース全体をインデックス化できます。これにより、次のようないくつかの利点が得られます。

  • コンテキスト認識: AI は、ファイルを手動で探して貼り付けることなく、BillingClient の初期化と build.gradle を自動的に見つけます。
  • 自動ファイル作成: AI は新しいソースセット(src/aptoide/java)を作成し、ファイルを移動できます。
  • 直接 PR 生成: これらの変更を新しいブランチに直接適用するよう AI に依頼でき、その後、通常のプルリクエストとしてレビューできます。

AI 統合後のチェック

AI は移行プロセスを大幅に加速できますが、課金は重要なシステムです。生成されたコードをコミットする前に、次の手動チェックを実行してください

1. プレースホルダーの確認

AI は Aptoide 公開鍵にプレースホルダーを使用します。build.gradle または BuildConfig 内のそれを、Aptoide アカウントにある実際の鍵に手動で置き換える必要があります。これを怠ると、SDK は購入結果の処理に失敗し、BillingResponseCodeDEVELOPER_ERROR (5) が発生します。

2. 依存関係のバージョン

AI モデルは、必ずしも Aptoide SDK の最新バージョンを把握しているとは限りません。最新の安定版リリースを使用していることを確認するために、build.gradle の実装バージョンを、当社の 公式 Maven リポジトリ と照合してください。

3. 消費ロジックのレビュー

Aptoide は consume 呼び出しを使用して取引を確定します。ステップ 5 で AI が生成したマッピング、特に「Acknowledge」呼び出しの処理方法を慎重にレビューしてください。非消費型アイテムとサブスクリプションが、アプリ固有の権利付与ロジックに従って処理されることを確認してください。

4. フレーバーの同期

課金クラスで参照されているすべてのリソース(文字列、ドローアブル、レイアウト)が、src/googlePlaysrc/aptoide の両方のソースセットに存在するか、または src/main に安全に移動されていることを確認してください。一方のフレーバーでリソースが欠落していると、その特定のバリアントが選択された場合にのみビルドが失敗します。

5. 最終的なサンドボックステスト

AI が生成したロジックが 100% 正確であると決して想定しないでください。コードが統合されたら、サンドボックス環境 ガイドに従って、リリース前にエンドツーエンドの完全なテストを実行してください。


使用例

Android Studio 組み込みの AI エージェントでこのプロンプトを使用する方法の例を次に示します。