构建消耗型数字交易 (Dialogflow)

本指南介绍了如何将数字交易添加到对话 使用户可以购买您的消耗型数字商品。

关键术语:消耗型数字商品是指库存量单位 (SKU), 用户可以多次使用和购买,例如一定数量的游戏代币 是 Android 游戏的理想平台此数字商品与非消耗品不同 用户只能购买一次的数字商品

有关消耗型一次性商品的详情,请参阅 Android 关于 一次性商品专用功能

限制和查看指南

其他政策适用于涉及交易的操作。这可能需要 查看包含交易的操作数,因此请将这一时间因素考虑在内 规划发布时间表。为了简化审核流程,请确保您符合 替换为 交易政策和准则 然后再提交 Action 以供审核。

销售数字商品的操作只能在以下国家/地区部署:

  • 澳大利亚
  • 巴西
  • 加拿大
  • 印度尼西亚
  • 日本
  • 墨西哥
  • 俄罗斯
  • 新加坡
  • 泰国
  • 土耳其
  • 英国
  • 美国

交易流程

本指南概述了数字商品中涉及的每个开发步骤 交易流程当您的 Action 处理数字商品交易时,它 采用以下流程:

  1. 设置数字购买 API 客户端:您的 Action 会使用数字 购买 API 与您的 Google Play 广告资源进行通信并进行交易。 在您的 Action 执行任何其他操作之前,它会创建一个具有 与数字购买 API 通信的服务密钥。
  2. 收集信息:您的 Action 会收集有关 用户和 Google Play 广告资源来为交易做准备
    1. 验证交易要求:您的 Action 使用数字 交易要求帮助程序(在购买流程开始时提供) 确保用户能够进行交易
    2. 收集可用的广告资源:您的 Action 检查您的 Google Play 广告资源,并确定当前可供购买的商品。
  3. 构建订单:您的 Action 会向用户展示可用的数字商品 以便用户选择一个商品进行购买。
  4. 完成购买:您的 Action 会使用 digitalPurchases API 来 通过用户从 Google Play 商店中选择的内容发起购买。
  5. 处理结果:您的 Action 会收到 并通知用户购买成功 其他步骤)。
  6. 确保购买交易可重复:您的 Action 会使用数字购买交易 通过 API 来“使用”使该商品可供购买 再次执行相应操作

前提条件

在将数字交易纳入你的 Action 之前,你需要 以下前提条件:

关联 Android 应用

如果您目前没有拥有结算权限的 Android 应用 Google Play 管理中心,请按以下步骤操作:

  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. 依次前往 BuildGenerate Signed Bundle / APK
    2. 点击下一步
    3. Key store path 下,点击 Create new
    4. 填写每个字段,然后点击 OK。记下您的密钥库 密码密钥密码,并妥善保存,因为 稍后会用到它们
    5. 点击下一步
    6. 选择发布
    7. 选择 V1 (JAR Signature)
    8. 点击完成
    9. 几秒钟后,Android Studio 会生成一个 app-release.apk 文件。 找到此文件以供稍后使用。
  6. Google Play 管理中心、 创建新应用。

  7. 前往应用版本页面。

  8. 封闭式轨道下,依次前往管理Alpha 版

  9. 点击创建版本按钮。

  10. 让 Google 管理和保护您的签名密钥下方,输入您的签名 关键信息

  11. 上传 APK 文件。

  12. 点击保存

创建你的数字商品

如果您当前在 Play 管理中心内没有任何数字商品,请按以下方法操作 步骤:

  1. Google Play 管理中心、 依次点击应用内商品受管理的商品。如果您看到警告 按照上述说明创建 Android 应用,或点击链接 创建商家资料。
  2. 点击创建受管理的商品
  3. 填写数字商品对应的字段。记下产品 ID 这就是您在 Action 中引用此商品的方式。
  4. 点击保存
  5. 针对您要销售的每件商品重复第 2-4 步。

Google Play 管理中心内的消耗品示例。

准备 Actions 项目

在 Google Play 管理中心内设置数字商品后,您必须启用 进行数字交易,并将您的 Actions 项目与您的 Play 应用相关联。

如需在 Actions 项目中启用数字商品交易,请按以下步骤操作: 步骤:

  1. Actions 控制台中,打开你的项目或创建一个新项目。
  2. 转到部署,然后选择目录信息
  3. 其他信息交易下,选中复选框 在您的 Action 会使用 Digital Purchase API 执行交易吗? 数字商品”
  4. 点击保存

创建数字商品 API 密钥

如需向数字商品 API 发送请求,您需要下载 JSON 服务 与 Actions 控制台项目关联的账号密钥。

如需检索您的服务账号密钥,请按以下步骤操作:

  1. Actions 控制台中,点击右上角的三点状图标。 然后选择项目设置
  2. 找到 Action 的 Project ID
  3. 访问此链接,替换“<project_id>”替换为您的项目 ID: https://console.developers.google.com/apis/credentials?project=project_id
  4. 在主导航栏中,前往凭据
  5. 在显示的页面上,点击创建凭据,然后点击服务 账号密钥
  6. 转到服务账号,然后点击新的服务账号
  7. 为服务账号命名,例如 digitaltransactions。
  8. 点击创建
  9. 角色设置为项目 >所有者
  10. 点击继续
  11. 点击创建密钥
  12. 选择 JSON 密钥类型。
  13. 点击创建密钥并下载 JSON 服务账号密钥。

请妥善保存此服务账号密钥。您将在自己的 执行方式为 DigitalPurchases API 创建客户端。

关联到您的 Play 广告资源

为了从 Actions 项目访问您的数字商品,您需要将您的 域名和应用 关联的媒体资源

注意:我们会在验证期间完成关联步骤,最多可能需要一周时间才能完成 媒体资源如果这段时间过后您的网站或应用还未建立关联, 与支持团队联系

如需将 Play 管理中心网站网域和应用关联到 Actions 项目,请按以下步骤操作: 具体步骤:

  1. Actions 控制台中,依次点击部署品牌验证
  2. 如果您尚未关联任何媒体资源,请先关联网站:

    1. 点击网络媒体资源 (&lt;/&gt;) 按钮。
    2. 输入您网域的网址,然后点击连接

    Google 会向 已在 Google Search Console。 这封电子邮件的收件人完成上述步骤后,网站应该就会 品牌验证下会显示相应信息。

  3. 您至少关联了一个网站后,请执行以下步骤 关联您的 Android 应用:

    1. Actions 控制台中,依次点击部署品牌验证
    2. 点击关联应用
    3. 在随即显示的页面上,按照说明验证网站 登录该网域选择包含 数字商品,然后输入与 品牌验证页面。

      Google 会再次向以下经过验证的所有者发送验证电子邮件: 网域。他们批准验证后,您的 Play 应用应该 品牌验证下会显示相应信息。

    4. 启用访问 Play 购买交易

显示已关联到 Actions 项目的网站和应用的图片。

构建购买流程

准备好 Actions 项目和数字商品清单后,构建数字商品 商品购买流程。

1. 设置数字购买 API 客户端

在对话 fulfillment 网络钩子中,使用您的服务创建一个 JWT 客户端 账号 JSON 密钥和 https://www.googleapis.com/auth/actions.purchases.digital 范围。

以下 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. 收集信息

您的 Action 会收集有关 用户购买行为的能力以及可通过 Google 地图购买哪些商品 广告资源。

2. a.验证交易要求

最好确保用户的账号设置妥当 ,然后再为用户提供购买选项。此步骤 包括检查用户是否配置了付款方式,以及是否处于 支持数字交易的语言区域。交易开始时 流程,请使用 DIGITAL_PURCHASE_CHECK 帮助程序验证用户的交易 配置。

以下 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.收集可用的广告资源

使用数字购买 API 请求您当前可用的 Play 商店 然后针对每个商品将其构建为 JSON 对象数组。 您稍后引用此数组以向用户显示可用的选项 供用户购买

您的每个数字商品都表示为一个 JSON 格式的 SKU。通过 以下 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 对象。

如需仅检索结果数组中的特定数字商品,请列出相应商品 数字商品 ID(如 Google Play 中每个应用内商品下方所示) 控制台)。body.ids

以下 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': ['consumable.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 对象的库存数组,并创建 列出响应,其中包含一个用于 :

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 帮助程序 intent 与 与用户选择的内容相关联。

以下 Node.js 代码会处理用户在列表响应中选择的 SKU 并请求包含相应信息的 COMPLETE_PURCHASE intent:

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. 处理结果

当购买完成时,它会触发 actions_intent_COMPLETE_PURCHASE Dialogflow 事件(或 actions.intent.COMPLETE_PURCHASE Actions SDK intent) 描述结果的 COMPLETE_PURCHASE_VALUE 参数。构建一个 intent 将结果传达给用户。

处理以下可能的购买结果:

  • 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);
  }
});

6. 使购买交易可重复

使用数字购买 API 请求您当前可用的 Play 商店 然后针对每个商品将其构建为 JSON 对象数组。 您稍后引用此数组以向用户显示可用的选项 供用户购买

您的每个数字商品都表示为一个 JSON 格式的 SKU。通过 以下 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 对象。

如需仅检索结果数组中的特定数字商品,请列出相应商品 数字商品 ID(如 Google Play 中每个应用内商品下方所示) 控制台)。body.ids

以下 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': ['consumable.1']
      },
    }, (err, httpResponse, body) => {
      if (err) {
        throw new Error(`API request error: ${err}`);
      }
      console.log(`${httpResponse.statusCode}: ${httpResponse.statusMessage}`);
      console.log(JSON.stringify(body));
    });
  });
});

反映用户的购买情况

当用户查询您的 Action 时,请求 JSON 的 user 对象会包含一个列表 用户购买的产品/服务请查看此信息并更改你的 Action 的回应 根据用户付费的内容付费

以下示例代码展示了请求的 user 对象,该对象包含 占之前应用内购买交易的 packageEntitlements com.digitalgoods.application 软件包:

  "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"
        }
      ]
    }
  ],
  ...
}