建構非消耗性數位交易

本指南說明如何將數位交易新增至對話動作,方便使用者購買非消耗性數位商品。

重要字詞:「非消耗性」數位商品是指只能購買一次的庫存單位 (SKU),例如在動作或 Android 應用程式中付費存取額外內容。這類產品與可購買、使用及重新購買的消耗性數位商品不同。

如要進一步瞭解非消耗性一次性產品,請參閱一次性產品專屬功能的 Android 說明文件。

交易流程

本指南概述數位商品交易流程中發生的每個開發步驟。動作處理數位商品的交易時,會使用下列流程:

  1. 設定 Digital Purchase API 用戶端:您的動作會使用 Digital Purchases API 與您的 Google Play 廣告空間進行通訊,並進行交易。在您的動作執行其他操作之前,系統會建立含有服務金鑰的 JWT 用戶端來與數位購買交易 API 通訊。
  2. 收集資訊:您的動作會收集使用者和 Google Play 清查的基本資訊,以便為交易準備。
    1. 驗證交易規定:您的動作會在購買流程開始時使用數位交易規定輔助程式,確保使用者可以進行交易。
    2. 收集可用廣告空間:您的動作會檢查 Google Play 商品目錄,並找出目前可購買的商品。
  3. 建立訂單:您的動作會向使用者顯示可用的數位商品,讓使用者選擇想要購買。
  4. 完成購買程序:您的動作會使用數位購買 API,在使用者選擇至 Google Play 商店後啟動購買程序。
  5. 處理結果:您的動作會收到交易的狀態碼,並通知使用者購買成功 (或需要採取其他步驟)。

限制和查看規範

「透過交易執行的操作」適用額外政策。我們可能需要數週的時間審查包含交易的動作,因此在規劃發布時間表時,請將這個時間納入考量。為簡化審查程序,請確保您遵守交易政策與規範,再將動作送審。

銷售數位商品的動作只能在下列國家/地區部署:

  • 澳洲
  • 巴西
  • 加拿大
  • 印尼
  • 日本
  • 墨西哥
  • 俄羅斯
  • 新加坡
  • 泰國
  • 土耳其
  • 英國
  • 美國

必要條件

將數位交易整合至動作之前,您必須具備下列必要條件:

  • 擁有開發人員帳戶和 Google Play 的商家帳戶,以便在 Google Play 管理中心管理數位商品。

  • 在 Google Search Console 中驗證的網域。 網域不需要與公開發布網站建立關聯,只需要參照您的網域即可。

  • 在 Google Play 管理中心內具備 com.android.vending.BILLING 權限的 Android 應用程式。您的數位商品將在 Google Play 管理中心與這個應用程式建立關聯的「應用程式內購」。

    此外,您還必須在 Play 管理中心使用這個應用程式建立版本,但如果您不想發布版本,可以建立封閉的 Alpha 版

    如果您尚未安裝 Android 應用程式,請按照這篇文章的「連結 Android 應用程式」指示操作。

  • Google Play 管理中心中的一或多項受管理產品,這些產品是您透過動作販售的數位商品。請注意,您必須先設定 Android 應用程式必要條件,才能在 Play 管理中心建立納入管理的產品。

    如果您尚未建立受管理的產品,請按照建立數位商品的說明操作。

與 Android 應用程式建立關聯

如果 Google Play 管理中心目前還沒有具備帳單權限的 Android 應用程式,請按照下列步驟操作:

  1. Android Studio 或您選擇的 Android IDE 中,建立新專案。請在專案設定提示中選擇選項,來建立非常基本的應用程式。
  2. 為專案設定套件名稱,例如 com.mycompany.myapp。請勿將這個名稱保留預設值,因為您無法將包含 com.example 的套件上傳至 Play 管理中心。
  3. 開啟應用程式的 AndroidManifest.xml 檔案。
  4. manifest 元素中加入以下這行程式碼:

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

    您的 AndroidManifest.xml 檔案應類似於以下程式碼區塊:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.mycompany.myapp">
        <uses-permission android:name="com.android.vending.BILLING" />
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme" />
    </manifest>
    
  5. 以已簽署的 APK 建構應用程式。在 Android Studio 中按照下列步驟操作:

    1. 前往「Build」,「Generate Signed Bundle / APK」
    2. 按一下「Next」
    3. 在「Key store path」下方,按一下「Create new」
    4. 填妥每個欄位,然後按一下「OK」。請記下您的「Key store Password」和「Key password」,並妥善保存這些資料,因為稍後會用到。
    5. 按一下「Next」
    6. 選取「release」
    7. 選取「V1 (JAR Signature)」
    8. 按一下「Finish」
    9. 幾秒後,Android Studio 會產生 app-release.apk 檔案。找出這個檔案以便日後使用。
  6. Google Play 管理中心建立新的應用程式。

  7. 前往應用程式版本頁面。

  8. 在「封閉測試群組」下方,依序前往「管理」和「Alpha 版」

  9. 按一下「Create Release」按鈕。

  10. 在「允許 Google 管理及保護您的簽署金鑰」下方,輸入您的簽署金鑰資訊。

  11. 上傳 APK 檔案。

  12. 點按「儲存」

建立數位商品

如果您在 Play 管理中心目前還沒有任何數位商品,請按照下列步驟操作:

  1. Google Play 管理中心中,依序前往「應用程式內產品」和「受管理的產品」。如果看到警告,請按照先前的操作說明建立 Android 應用程式,或按一下連結來建立商家檔案。
  2. 按一下「建立受管理的產品」
  3. 填寫數位產品的欄位。請記下產品 ID,這個 ID 方便您在動作中參照這項產品。
  4. 點按「儲存」
  5. 針對您要銷售的每個產品重複執行步驟 2 到 4。

Google Play 管理中心的非消耗性商品示例。

準備動作專案

在 Google Play 管理中心設定數位商品後,您必須啟用數位交易,並將動作專案與 Play 應用程式建立關聯。

設定

如要在動作專案中啟用數位商品交易,請按照下列步驟操作:

  1. Actions 主控台中,開啟專案或建立新專案。
  2. 依序前往「部署」和「目錄資訊」
  3. 在「額外資訊」和「交易」下方,勾選「Do your Actions use the Digital Purchase API to 執行數位商品的交易」底下的「Yes」方塊。
  4. 點按「儲存」

建立數位商品 API 金鑰

如要將要求傳送至數位商品 API,您必須下載與 Actions 主控台專案相關聯的 JSON 服務帳戶金鑰。

如要擷取服務帳戶金鑰,請按照下列步驟操作:

  1. 在「Actions 主控台」中,按一下右上角的三點圖示,然後點選「Project settings」
  2. 找出動作的專案 ID
  3. 請點選這個連結,並將「<project_id>」替換成您的專案 ID:https://console.developers.google.com/apis/credentials?project=project_id
  4. 在主要導覽選單中,前往「憑證」
  5. 在顯示的頁面中,依序按一下「建立憑證」和「服務帳戶金鑰」
  6. 前往「Service Account」,然後按一下「New Service Account」
  7. 為服務帳戶命名,例如數位交易。
  8. 點選「建立」
  9. 將「Role」(角色) 設為 [Project] (專案) > [Owner] (擁有者)
  10. 按一下 [繼續]。
  11. 按一下 [Create Key] (建立金鑰)
  12. 選取「JSON」金鑰類型。
  13. 按一下「建立金鑰」,並下載 JSON 服務帳戶金鑰。

請將這個服務帳戶金鑰存放在安全的地方。您會在執行要求中使用這組金鑰,為數位購買交易 API 建立用戶端。

連結至您的 Play 廣告空間

如要從 Actions 專案存取數位商品,請將您的網站網域和應用程式與專案建立關聯,做為已連結的屬性

如要將 Play 管理中心網域和應用程式連結至動作專案,請按照下列步驟操作:

  1. 動作控制台中,依序前往「部署」和「品牌驗證」
  2. 如果您尚未連結任何資源,請先連結網站:

    1. 按一下 [網站資源] 按鈕。</>
    2. 輸入您網域的網址,然後按一下「Connect」

    Google 會透過電子郵件,將進一步操作說明傳送給在 Google Search Console 中驗證該網域的使用者。收到這封電子郵件的收件者完成這些步驟後,網站應會顯示在「品牌驗證」下方。

  3. 擁有至少一個已連結的網站後,請執行下列步驟以連結 Android 應用程式:

    1. 動作控制台中,依序前往「部署」和「品牌驗證」
    2. 按一下 [連結應用程式]
    3. 在隨即顯示的頁面中,按照操作說明驗證您在 Play 管理中心的網域。選取含有您數位商品的 Play 應用程式,然後輸入「品牌驗證」頁面上顯示的網域網址。

      再一次,Google 會傳送驗證電子郵件給網域的已驗證擁有者。核准驗證後,您的 Play 應用程式應會顯示在「品牌驗證」下方。

    4. 啟用「存取 Play 購買項目」

此圖片顯示已連結至 Actions 專案的網站和應用程式。

建立購買流程

備妥 Actions 專案和數位商品庫存後,請在對話執行要求 Webhook 中建立數位商品購買流程。

1. 設定數位購物 API 用戶端

在對話執行要求 Webhook 中,使用服務帳戶 JSON 金鑰和 https://www.googleapis.com/auth/actions.purchases.digital 範圍建立 JWT 用戶端。

下列 Node.js 程式碼會為數位購買交易 API 建立 JWT 用戶端:

  const serviceAccount = {'my-file.json'};
  const request = require('request');
  const {google} = require('googleapis');

  const jwtClient = new google.auth.JWT(
    serviceAccount.client_email, null, serviceAccount.private_key,
    ['https://www.googleapis.com/auth/actions.purchases.digital'],
    null
  );

2. 收集資訊

使用者購買商品之前,您的動作會收集有關使用者進行購買交易的功能,以及您的商品目錄中有哪些商品的相關資訊。

2. a. 驗證數位購買規定

建議先確認使用者帳戶已設定為可執行交易,使用者才會提供購買選項。您應轉換至 DigitalPurchaseCheck 情境,藉此確認使用者已通過驗證,確認使用者是在允許的途徑 (智慧螢幕、智慧音箱或 Android) 中進行交易,且使用者位於支援數位交易的語言代碼。

如要建立數位購物支票的場景,請按照下列步驟操作:

  1. 在「Scenes」分頁中新增名為 DigitalPurchaseCheck 的場景。
  2. 在「運算單元填充」下方,按一下「+」來新增版位。
  3. 在「Select type」(選取類型) 下方,選取 actions.type.DigitalPurchaseCheckResult 做為運算單元類型。
  4. 在運算單元名稱欄位中,為版位提供名稱 DigitalPurchaseCheck
  5. 勾選「Customize slot value writeback」核取方塊 (預設為啟用)。
  6. 點按「儲存」

數位購物檢查會產生下列其中一種結果:

  • 如果符合要求,系統會設定工作階段參數和成功條件,然後您可以繼續允許使用者購買數位商品。
  • 如果無法符合一或多項要求,工作階段參數會設為失敗條件。在這種情況下,您應該從交易體驗中引導對話方向,或是結束對話。

如要處理數位購物檢查結果,請按照下列步驟操作:

  1. 在「Scenes」分頁中,選取新建立的 DigitalPurchaseCheck 場景。
  2. 在「條件」下方,按一下「+」新增條件。
  3. 在文字欄位中,輸入下列條件語法來檢查成功條件:

    scene.slots.status == "FINAL" && session.params.DigitalPurchaseCheck.resultType == "CAN_PURCHASE"
    
  4. 將遊標懸停在剛剛新增的條件上,然後按一下向上箭頭,將遊標放在 if scene.slots.status == "FINAL" 之前。

  5. 啟用「Send 提示」,並提供簡單的提示,讓使用者知道他們已準備好進行交易:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                You are ready to purchase digital goods.
    
  6. 在「Transition」下方選取另一個場景,讓使用者可以繼續進行對話並繼續進行交易。

  7. 選取條件圖示 else if scene.slots.status == "FINAL"

  8. 啟用「Send 提示」,並透過簡單提示,讓使用者瞭解他們無法完成交易:

    candidates:
      - first_simple:
          variants:
            - speech: Sorry you cannot perform a digital purchase.
    
  9. 選取「轉換」下方的「結束對話」即可結束對話。

2. b. 收集可用廣告空間

使用數位購買項目 API 要求目前可用的 Play 商店庫存,然後將該庫存建構到各個產品的 JSON 物件陣列中。您稍後可以參考這個陣列,向使用者顯示哪些購買選項。

您的每項數位商品都會以 JSON 格式表示。下列 Node.js 程式碼概述每個 SKU 的預期格式:

body = {
  skus: [
    skuId: {
      skuType: one of "SKU_TYPE_IN_APP" or "SKU_TYPE_SUBSCRIPTION"
      id: string,
      packageName: string
    }
    formattedPrice: string,
    title: string,
    description: string
  ]
}

將 POST 要求傳送至 https://actions.googleapis.com/v3/packages/{packageName}/skus:batchGet 端點,其中 {packageName} 是 Google Play 管理中心內的應用程式的套件名稱 (例如 com.myapp.digitalgoods),然後將結果格式化為 SKU 物件陣列。

如果只要在結果陣列中擷取特定數位商品,請列出您想在 body.ids 中購買的數位商品 (如 Google Play 管理中心各項應用程式內商品下方所示) 的產品 ID。

下列 Node.js 程式碼會要求數位購買交易 API 提供的可用商品清單,並將結果格式化為 SKU 陣列:

return jwtClient.authorize((err, tokens) => {
    if (err) {
      throw new Error(`Auth error: ${err}`);
    }

    const packageName = 'com.example.projectname';

    request.post(`https://actions.googleapis.com/v3/packages/${packageName}/skus:batchGet`, {
      'auth': {
        'bearer': tokens.access_token,
      },
      'json': true,
      'body': {
        'conversationId': conv.session.id,
        'skuType': 'SKU_TYPE_IN_APP',
        // This request is filtered to only retrieve SKUs for the following product IDs
        'ids': ['nonconsumable.1']
      },
    }, (err, httpResponse, body) => {
      if (err) {
        throw new Error(`API request error: ${err}`);
      }
      console.log(`${httpResponse.statusCode}: ${httpResponse.statusMessage}`);
      console.log(JSON.stringify(body));
    });
  });
});

3. 建立訂單

如要開始使用者的數位購買交易,請顯示可供購買的數位商品清單。您可以使用各種豐富的回應類型來代表庫存,並提示使用者做出選擇。

下列 Node.js 程式碼會讀取 SKU 物件的庫存陣列,並建立清單回應,以及每個清單項目:

const items = [];
const entries = [];
skus.forEach((sku) => {
   const key = `${sku.skuId.skuType},${sku.skuId.id}`
   items.push({
       key: key
   });
   entries.push({
       name: key,
       synonyms: [],
       display: {
           title: sku.title,
           description: `${sku.description} | ${sku.formattedPrice}`,
       }
   });
});

conv.session.typeOverrides = [{
   name: 'type_name',
   mode: 'TYPE_REPLACE',
   synonym: {
       entries: entries
   }
}];

conv.add(new List({
   title: 'List title',
   subtitle: 'List subtitle',
   items: items,
}));

根據使用者所選項目建立購買交易

使用者選取項目後,您就可以建立訂單。如要這麼做,您可以在與所選項目相關聯的版位上呼叫 Webhook,以建立訂單。透過執行要求,將訂單資料儲存至工作階段參數。順序物件會在相同工作階段的多個場景中使用。

conv.session.params.purchase = {
  "@type": "type.googleapis.com/google.actions.transactions.v3.CompletePurchaseValueSpec",
  "skuId": {
    "skuType": "<SKU_TYPE_IN_APP>",
    "id": "<SKU_ID>",
    "packageName": "<PACKAGE_NAME>"
  },
  "developerPayload": ""
};

在 Actions Builder 中,您可以改用 JSON 編輯器,使用上述訂單物件設定運算單元。這兩種實作都使用 CompletePurchaseValueSpec 格式,詳情請參閱 JSON Webhook 酬載參考資料

4. 完成購買程序

使用者選取某個商品後,您就可以完成交易。填入與所選項目相關聯的版位後,您應轉換至執行完成購買交易的場景。

建立完整購買場景

  1. 在「Scenes」分頁中新增名稱為 CompletePurchase 的新場景。
  2. 在「運算單元填充」下方,按一下「+」來新增版位。
  3. 在「Select type」(選取類型) 下方,選取 actions.type.CompletePurchaseValue 做為運算單元類型。
  4. 在運算單元名稱欄位中,為版位提供名稱 CompletePurchase
  5. 勾選「CustomizeSlot value writeback」(自訂運算單元值寫入) 核取方塊 (預設為啟用)。
  6. 在「ConfigureSlot」下方的下拉式選單中選取 Use session parameter
  7. 在「ConfigureSlot」(設定運算單元) 下方,在文字欄位輸入用來儲存訂單的工作階段參數名稱 (即 $session.params.purchase)。
  8. 點按「儲存」

5. 處理結果

類型為 actions.type.CompletePurchaseValue 的運算單元可能會有下列結果:

  • PURCHASE_STATUS_OK:購買成功。此時交易已完成,因此請結束交易流程,並回到對話。
  • PURCHASE_STATUS_ALREADY_OWNED:使用者擁有該項目,交易失敗。如要避免發生這項錯誤,請檢查使用者先前的購買交易,並調整顯示的商品,以免使用者無法選擇重新購買他們已有的商品。
  • PURCHASE_STATUS_ITEM_UNAVAILABLE:要求的項目無法使用,因此交易失敗。如要避免發生這項錯誤,請在購買購買時更靠近可用的 SKU。
  • PURCHASE_STATUS_ITEM_CHANGE_REQUESTED:使用者決定購買其他商品,導致交易失敗。請重新提示建立訂單,讓使用者可以立即做出其他決定。
  • PURCHASE_STATUS_USER_CANCELLED:使用者已取消購買流程,導致交易失敗。由於使用者提早退出流程,因此請詢問使用者是否要重試交易,或完全結束交易。
  • PURCHASE_STATUS_ERROR:交易失敗,原因不明。通知使用者交易失敗,並詢問是否要再試一次。
  • PURCHASE_STATUS_UNSPECIFIED:交易因不明原因而失敗,因此導致狀態不明。如要處理此錯誤狀態,您可以通知使用者交易失敗,並詢問是否要再試一次。

您應處理 CompletePurchase 場景中的每個結果。

  1. 在「Scenes」分頁中,選取新建立的 CompletePurchase 場景。
  2. 在「條件」下方,按一下「+」新增條件。
  3. 在文字欄位中,輸入下列條件語法來檢查成功條件:

    scene.slots.status == "FINAL" && session.params.CompletePurchase.purchaseStatus == "PURCHASE_STATUS_OK"
    
  4. 將遊標懸停在剛剛新增的條件上,然後按一下向上箭頭,將遊標放在 if scene.slots.status == "FINAL" 之前。

  5. 啟用「Send 提示」,並提供簡單的提示,讓使用者知道他們已準備好進行交易:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Your purchase was successful.
    
  6. 在「轉換」下方,選取「結束對話」即可結束對話。

針對您想支援的購買結果類型,重複上述步驟。

反映使用者的購買交易

當使用者查詢您的動作時,要求的 JSON 的 user 物件會包含他們的購買交易清單。請查看這項資訊,並根據使用者已付費的內容變更動作的回應。

以下程式碼範例顯示要求的 user 物件,其中包含了他們為 com.digitalgoods.application 套件所進行應用程式內購的 packageEntitlements

{
  "handler": {
    "name": "handler_name"
  },
  "intent": {
    "name": "actions.intent.MAIN",
    "params": {},
    "query": ""
  },
  "scene": {
    "name": "SceneName",
    "slotFillingStatus": "UNSPECIFIED",
    "slots": {}
  },
  "session": {
    "id": "example_session_id",
    "params": {},
    "typeOverrides": []
  },
  "user": {
    "locale": "en-US",
    "params": {
      "verificationStatus": "VERIFIED"
      "packageEntitlements": [
        {
          "packageName": "com.digitalgoods.application",
          "entitlements": [
            {
              "sku": "non-consumable.1",
              "skuType": "SKU_TYPE_IN_APP"
            }
            {
              "sku": "consumable.2",
              "skuType": "SKU_TYPE_IN_APP"
            }
          ]
        },
        {
          "packageName": "com.digitalgoods.application",
          "entitlements": [
            {
              "sku": "annual.subscription",
              "skuType": "SKU_TYPE_SUBSCRIPTION",
              "inAppDetails": {
                "inAppPurchaseData": {
                  "autoRenewing": true,
                  "purchaseState": 0,
                  "productId": "annual.subscription",
                  "purchaseToken": "12345",
                  "developerPayload": "HSUSER_IW82",
                  "packageName": "com.digitalgoods.application",
                  "orderId": "GPA.233.2.32.3300783",
                  "purchaseTime": 1517385876421
                },
                "inAppDataSignature": "V+Q=="
              }
            }
          ]
        }
      ]
     }
   },
  "homeStructure": {
    "params": {}
  },
  "device": {
    "capabilities": [
      "SPEECH",
      "RICH_RESPONSE",
      "LONG_FORM_AUDIO"
    ]
  }
}

測試專案

測試專案時,您可以在動作主控台中啟用沙箱模式,以便在不透過付款方式收費的情況下測試動作。如要啟用沙箱模式,請按照下列步驟操作:

  1. 在 Actions 控制台的導覽面板中,按一下「測試」
  2. 按一下「設定」
  3. 啟用「Development Sandbox」選項。