本指南說明如何將數位訂閱交易新增至對話動作,方便使用者購買訂閱項目。
重要字詞:「訂閱」數位商品是一種儲備單位 (SKU),需要定期向使用者收費,例如線上雜誌。這與「消耗性」數位商品不同,使用者必須手動重新購買,或是「非消耗性」數位商品,只會自動購買一次。
如要進一步瞭解數位訂閱,請參閱 Android 說明文件的訂閱專屬功能。
限制和查看規範
「透過交易執行的操作」適用額外政策。我們可能需要數週的時間審查包含交易的動作,因此在規劃發布時間表時,請將這個時間納入考量。為簡化審查程序,請確保您遵守交易政策與規範,再將動作送審。
銷售數位商品的動作只能在下列國家/地區部署:
- 澳洲
- 巴西
- 加拿大
- 印尼
- 日本
- 墨西哥
- 俄羅斯
- 新加坡
- 泰國
- 土耳其
- 英國
- 美國
交易流程
本指南概述數位商品交易流程中發生的每個開發步驟。動作處理數位商品的交易時,會使用下列流程:
- 設定 Digital Purchase API 用戶端:您的動作會使用 Digital Purchases API 與您的 Google Play 廣告空間進行通訊,並進行交易。在您的動作執行其他操作之前,系統會建立含有服務金鑰的 JWT 用戶端來與數位購買交易 API 通訊。
- 收集資訊:您的動作會收集使用者和 Google Play 清查的基本資訊,以便為交易準備。
- 建立訂單:您的動作會向使用者顯示可用的數位商品,讓使用者選擇想要購買。
- 完成購買程序:您的動作會使用數位購買 API,在使用者選擇至 Google Play 商店後啟動購買程序。
- 處理結果:您的動作會收到交易的狀態碼,並通知使用者購買成功 (或採取其他步驟)。
必要條件
將數位交易整合至動作之前,您必須具備下列必要條件:
擁有開發人員帳戶和 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 應用程式,請按照下列步驟操作:
- 在 Android Studio 或您選擇的 Android IDE 中,建立新專案。請在專案設定提示中選擇選項,來建立非常基本的應用程式。
- 為專案設定套件名稱,例如
com.mycompany.myapp
。請勿將這個名稱保留預設值,因為您無法將包含com.example
的套件上傳至 Play 管理中心。 - 開啟應用程式的
AndroidManifest.xml
檔案。 在
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>
以已簽署的 APK 建構應用程式。在 Android Studio 中按照下列步驟操作:
- 前往「Build」,「Generate Signed Bundle / APK」。
- 按一下「Next」。
- 在「Key store path」下方,按一下「Create new」。
- 填妥每個欄位,然後按一下「OK」。請記下您的「Key store Password」和「Key password」,並妥善保存這些資料,因為稍後會用到。
- 按一下「Next」。
- 選取「release」。
- 選取「V1 (JAR Signature)」。
- 按一下「Finish」。
- 幾秒後,Android Studio 會產生
app-release.apk
檔案。找出這個檔案以便日後使用。
在 Google Play 管理中心建立新的應用程式。
前往應用程式版本頁面。
在「封閉測試群組」下方,依序前往「管理」和「Alpha 版」。
按一下「Create Release」按鈕。
在「允許 Google 管理及保護您的簽署金鑰」下方,輸入您的簽署金鑰資訊。
上傳 APK 檔案。
點按「儲存」。
建立數位商品
如果您在 Play 管理中心目前還沒有任何數位商品,請按照下列步驟操作:
- 在 Google Play 管理中心中,依序前往「應用程式內產品」和「訂閱項目」。如果看到警告,請按照先前的操作說明建立 Android 應用程式,或按一下連結來建立商家檔案。
- 按一下 [Create Subscription] (建立訂閱項目)。
- 填寫數位產品的欄位。請記下產品 ID,這個 ID 方便您在動作中參照這項產品。
- 點按「儲存」。
- 針對您要銷售的每個產品重複執行步驟 2 到 4。
準備動作專案
在 Google Play 管理中心設定數位商品後,您必須啟用數位交易,並將動作專案與 Play 應用程式建立關聯。
如要在動作專案中啟用數位商品交易,請按照下列步驟操作:
- 在 Actions 主控台中,開啟專案或建立新專案。
- 依序前往「部署」和「目錄資訊」。
- 在「額外資訊」和「交易」下方,勾選「Do your Actions use the Digital Purchase API to 執行數位商品的交易」底下的「Yes」方塊。
- 點按「儲存」。
建立數位商品 API 金鑰
如要將要求傳送至數位商品 API,您必須下載與 Actions 主控台專案相關聯的 JSON 服務帳戶金鑰。
如要擷取服務帳戶金鑰,請按照下列步驟操作:
- 在「Actions 主控台」中,按一下右上角的三點圖示,然後點選「Project settings」。
- 找出動作的專案 ID。
- 請點選這個連結,並將「
<project_id>
」替換成您的專案 ID:https://console.developers.google.com/apis/credentials?project=project_id
- 在主要導覽選單中,前往「憑證」。
- 在顯示的頁面中,依序按一下「建立憑證」和「服務帳戶金鑰」。
- 前往「Service Account」,然後按一下「New Service Account」。
- 為服務帳戶命名,例如數位交易。
- 點選「建立」。
- 將「Role」(角色) 設為 [Project] (專案) > [Owner] (擁有者)。
- 按一下 [繼續]。
- 按一下 [Create Key] (建立金鑰)。
- 選取「JSON」金鑰類型。
- 按一下「建立金鑰」,並下載 JSON 服務帳戶金鑰。
請將這個服務帳戶金鑰存放在安全的地方。您會在執行要求中使用這組金鑰,為數位購買交易 API 建立用戶端。
連結至您的 Play 廣告空間
如要從 Actions 專案存取數位商品,請將您的網站網域和應用程式與專案建立關聯,做為已連結的屬性。
注意:我們驗證資源時,連結步驟最多可能需要一週才能完成。如果您的網站或應用程式在 24 小時後仍未連結,請與支援團隊聯絡。
如要將 Play 管理中心網域和應用程式連結至動作專案,請按照下列步驟操作:
- 在動作控制台中,依序前往「部署」和「品牌驗證」。
如果您尚未連結任何資源,請先連結網站:
- 按一下 [網站資源] 按鈕。</>
- 輸入您網域的網址,然後按一下「Connect」。
Google 會透過電子郵件,將進一步操作說明傳送給在 Google Search Console 中驗證該網域的使用者。收到這封電子郵件的收件者完成這些步驟後,網站應會顯示在「品牌驗證」下方。
擁有至少一個已連結的網站後,請執行下列步驟以連結 Android 應用程式:
- 在動作控制台中,依序前往「部署」和「品牌驗證」。
- 按一下 [連結應用程式]。
在隨即顯示的頁面中,按照操作說明驗證您在 Play 管理中心的網域。選取含有您數位商品的 Play 應用程式,然後輸入「品牌驗證」頁面上顯示的網域網址。
再一次,Google 會傳送驗證電子郵件給網域的已驗證擁有者。核准驗證後,您的 Play 應用程式應會顯示在「品牌驗證」下方。
啟用「存取 Play 購買項目」。
建立購買流程
備妥 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. 驗證交易規定
建議先確認使用者帳戶已設為可執行交易,再讓他們選擇購買商品。這個步驟包括檢查使用者是否已設定付款方式,以及他們位於支援數位交易的語言代碼。請在交易流程開始時,使用 DIGITAL_PURCHASE_CHECK
輔助程式透過 Google 助理驗證使用者的交易設定。
下列 Node.js 程式碼會在對話開始時使用 DIGITAL_PURCHASE_CHECK
:
app.intent('Default Welcome Intent', async (conv, { SKU }) => {
// Immediately invoke digital purchase check intent to confirm
// purchase eligibility.
conv.ask(new DigitalPurchaseCheck());
});
在對話引數中,以 DIGITAL_PURCHASE_CHECK_RESULT
的形式找出這項檢查的結果。您可以根據上述結果,繼續交易流程或退出交易,並提示他們檢查 Google Pay 設定。
下列 Node.js 程式碼會處理需求檢查結果:
app.intent('Digital Purchase Check', async (conv) => {
const arg = conv.arguments.get('DIGITAL_PURCHASE_CHECK_RESULT');
if (!arg || !arg.resultType) {
conv.close('Digital Purchase check failed. Please check logs.');
return;
}
// User does not meet necessary conditions for completing a digital purchase
if (arg.resultType === 'CANNOT_PURCHASE' || arg.resultType === 'RESULT_TYPE_UNSPECIFIED') {
conv.close(`It looks like you aren't able to make digital purchases. Please check your Google Pay configuration and try again.`);
return;
}
conv.ask('Welcome to the Digital Goods Sample. Would you like to see what I have for sale?');
});
2. b. 收集可用廣告空間
使用數位購買項目 API 要求目前可用的 Play 商店庫存,然後將該庫存建構到各個產品的 JSON 物件陣列中。您稍後可以參考這個陣列,向使用者顯示哪些購買選項。
您的每項數位商品都會以 JSON 格式表示。下列 Node.js 程式碼概述每個 SKU 的預期格式:
body = {
skus: [
skuId: {
skuType: one of "APP" or "UNSPECIFIED"
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': conversationId,
'skuType': 'APP',
// This request is filtered to only retrieve SKUs for the following product IDs
'ids': ['annual.subscription']
},
}, (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 物件的庫存陣列,並建立清單回應,以及每個清單項目:
skus.forEach((sku) => {
const key = `${sku.skuId.skuType},${sku.skuId.id}`
list.items[key] = {
title: sku.title,
description: `${sku.description} | ${sku.formattedPrice}`,
};
});
4. 完成購買程序
如要完成購買程序,請搭配使用者選取的項目使用 COMPLETE_PURCHASE
輔助意圖。
下列 Node.js 程式碼會從清單回應處理使用者選取的 SKU,並使用該資訊要求 COMPLETE_PURCHASE
意圖:
app.intent('Send Purchase', (conv, params, option) => {
let [skuType, id] = option.split(',');
conv.ask(new CompletePurchase({
skuId: {
skuType: skuType,
id: id,
packageName: <PACKAGE_NAME>,
},
}));
});
5. 處理結果
購買交易完成後,系統會使用 COMPLETE_PURCHASE_VALUE
引數描述結果,觸發 actions_intent_COMPLETE_PURCHASE
Dialogflow 事件 (或 actions.intent.COMPLETE_PURCHASE
Actions SDK 意圖)。建構由此事件觸發的意圖,並向使用者傳達結果。
請處理下列可能的購買結果:
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
:交易因不明原因失敗,導致狀態不明。如要處理此錯誤狀態,請讓使用者知道交易失敗,並詢問是否要再試一次。
以下 Node.js 程式碼會讀取 COMPLETE_PURCHASE_VALUE
引數並處理每個結果:
app.intent('Purchase Result', (conv) => {
const arg = conv.arguments.get('COMPLETE_PURCHASE_VALUE');
console.log('User Decision: ' + JSON.stringify(arg));
if (!arg || !arg.purchaseStatus) {
conv.close('Purchase failed. Please check logs.');
return;
}
if (arg.purchaseStatus === 'PURCHASE_STATUS_OK') {
conv.close(`Purchase completed! You're all set!`);
} else if (arg.purchaseStatus === 'PURCHASE_STATUS_ALREADY_OWNED') {
conv.close('Purchase failed. You already own this item.');
} else if (arg.purchaseStatus === 'PURCHASE_STATUS_ITEM_UNAVAILABLE') {
conv.close('Purchase failed. Item is not available.');
} else if (arg.purchaseStatus === 'PURCHASE_STATUS_ITEM_CHANGE_REQUESTED') {
// Reprompt with your item selection dialog
} else {
conv.close('Purchase Failed:' + arg.purchaseStatus);
}
});
反映使用者的購買交易
當使用者查詢您的動作時,要求的 JSON 的 user
物件會包含他們的購買交易清單。請查看這項資訊,並根據使用者付費的內容變更動作的回應。
以下程式碼範例顯示要求的 user
物件,其中包含了他們為 com.digitalgoods.application
套件所進行應用程式內購的 packageEntitlements
:
"user": {
"userId": "xxxx",
"locale": "en-US",
"lastSeen": "2018-02-09T01:49:23Z",
"packageEntitlements": [
{
"packageName": "com.digitalgoods.application",
"entitlements": [
{
"sku": "non-consumable.1",
"skuType": "APP"
}
{
"sku": "consumable.2",
"skuType": "APP"
}
]
},
{
"packageName": "com.digitalgoods.application",
"entitlements": [
{
"sku": "annual.subscription",
"skuType": "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=="
}
}
]
}
]
},
"conversation": {
"conversationId": "1518141160297",
"type": "NEW"
},
"inputs": [
{
"intent": "actions.intent.MAIN",
"rawInputs": [
{
"inputType": "VOICE",
"query": "Talk to My Test App"
}
]
}
],
...
}