이 가이드에서는 대화형 앱에 디지털 거래를 추가하는 방법을 설명합니다. 사용자가 소비성 디지털 상품을 구매할 수 있도록 하는 액션
핵심 용어: 소비성 디지털 상품은 재고 유지 단위 (SKU)로서 사용자가 두 번 이상 사용하고 구매할 수 있음(예: 인게임 화폐의 양) Android 게임용입니다. 이 디지털 상품은 비소비성 상품과 다릅니다. 사용자가 한 번만 구매할 수 있는 디지털 상품
소비성 일회성 제품에 대한 자세한 내용은 Android 자세한 내용은 일회성 제품별 기능
제한사항 및 검토 가이드라인
거래가 있는 작업에는 추가 정책이 적용됩니다. 몇 분 정도 걸릴 수 있습니다. 거래가 포함된 액션을 검토할 수 있으므로 출시 일정을 계획하는 데 도움이 됩니다 검토 절차가 수월하게 진행될 수 있도록 다음 코드로 교체합니다. 거래 정책 및 가이드라인 을 검토하세요.
디지털 상품을 판매하는 작업은 다음 국가에서만 배포할 수 있습니다.
- 오스트레일리아
- 브라질
- 캐나다
- 인도네시아
- 일본
- 멕시코
- 러시아
- 싱가포르
- 태국
- 튀르키예
- 영국
- 미국
거래 흐름
이 가이드에서는 디지털 상품에서 발생하는 각 개발 단계를 간략히 설명합니다. 거래 흐름에 따라 달라집니다 작업에서 디지털 상품 거래를 처리할 때 다음과 같은 흐름을 사용합니다.
- 디지털 구매 API 클라이언트 설정: 작업에서 디지털 구매 구매 API를 사용하여 Google Play 인벤토리와 통신하고 거래할 수 있습니다. 작업은 다른 작업을 수행하기 전에 서비스 키를 사용하여 디지털 구매 API와 통신할 수 있습니다.
- 정보 수집: 작업이
사용자와 Google Play 인벤토리를 연결하여 거래를 준비합니다.
- 거래 요건 확인: 작업에서 디지털을 사용합니다. 거래 요구사항 도우미에 추가하여 사용자가 거래할 수 있는지 확인합니다
- 사용 가능한 인벤토리 수집: 작업에서 Google Play를 확인합니다. 현재 구매할 수 있는 상품을 식별합니다.
 
- 주문하기: 작업에서 사용 가능한 디지털 상품을 제시합니다. 사용자가 구매할 제품을 선택할 수 있습니다.
- 구매 완료: 작업에서 디지털 구매 API를 사용하여 Google Play 스토어에서 사용자가 선택한 항목으로 구매를 시작합니다.
- 결과 처리: 작업이 사용자에게 구매가 완료되었다고 알리거나 추가 단계).
- 반복 가능한 구매로 만들기: 작업에서 디지털 구매를 사용합니다. '소비'하는 API 해당 항목을 구입할 수 있도록 만드는 것입니다. 다시 표시합니다.
기본 요건
디지털 거래를 작업에 통합하려면 다음이 필요합니다. 다음과 같은 전제조건이 있습니다.
- 가 개발자 계정 및 판매자 계정 디지털 상품을 관리할 수 있습니다. Google Play Console 
- 웹 도메인으로 Google Search Console에서 인증되어야 합니다. 이 도메인은 공개 웹사이트와 연결되어 있지 않아도 됩니다. 웹 도메인을 참조하기만 하면 됩니다. 
- com.android.vending.BILLING를 사용하는 Android 앱 권한 Google Play Console에서 확인할 수 있습니다. 디지털 상품이 '인앱 구매'가 됩니다. 앱 관련 정보를 확인할 수 있습니다.- 이 앱으로 Play Console에서도 버전을 만들어야 하지만 발표곡을 공개하지 않으려면 비공개 알파 버전을 버전을 참조하세요. - 아직 Android 앱이 없다면 Android 앱 연결 안내 
- 다음 카테고리에 있는 하나 이상의 관리 제품: Google Play Console 디지털 상품을 말합니다. 참고: Play Console에서 관리 제품을 만들 수 없습니다. Android 앱 필수요건. - 아직 관리되는 제품이 없다면 디지털 상품 안내 만들기 
Android 앱 연결
현재 Play Console에서 앱을 다운로드하려면 다음 단계를 따르세요.
- Android 스튜디오 또는 새 프로젝트를 만듭니다. 옵션 선택 프로젝트 설정 프롬프트가 표시되면 매우 기본적인 앱을 만들 수 있습니다.
- 프로젝트에 패키지 이름(예: com.mycompany.myapp)을 지정합니다. 이 이름을 기본값으로 두지 마세요. Play Console에com.example를 포함합니다.
- 앱의 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 스튜디오에서 다음 단계를 따르세요. - Build, Generate Signed Bundle / APK로 이동합니다.
- 다음을 클릭합니다.
- Key store path에서 Create new를 클릭합니다.
- 각 입력란을 작성하고 확인을 클릭합니다. 키 저장소를 기록해 두세요. 비밀번호와 키 비밀번호를 보관하고 안전한 장소에 보관해야 합니다. 나중에 사용할 것입니다.
- 다음을 클릭합니다.
- 출시를 선택합니다.
- V1 (JAR Signature)을 선택합니다.
- 마침을 클릭합니다.
- 몇 초 후에 Android 스튜디오에서 app-release.apk파일을 생성합니다. 나중에 사용할 수 있도록 이 파일을 찾습니다.
 
- Google Play Console 새 애플리케이션을 만듭니다 
- 앱 버전으로 이동합니다. 
- 비공개 트랙에서 관리, 알파로 차례로 이동합니다. 
- Create Release(버전 만들기) 버튼을 클릭합니다. 
- Google에서 서명 키를 관리하고 보호하도록 허용 아래에 서명을 입력합니다. 핵심 정보 
- APK 파일을 업로드합니다. 
- 저장을 클릭합니다. 
디지털 상품 만들기
현재 Play Console에 디지털 상품이 없다면 다음 안내를 따르세요. 단계:
- Google Play Console 인앱 상품 > 관리되는 제품으로 이동합니다. 경고가 표시되면 이전 안내에 따라 Android 앱을 만들거나 링크를 클릭합니다. 판매자 프로필을 만드세요
- 관리되는 제품 만들기를 클릭합니다.
- 디지털 제품 입력란을 작성합니다. 제품 ID를 기록해 두세요. 이는 작업에서 이 제품을 참조하는 방법입니다.
- 저장을 클릭합니다.
- 판매하려는 각 제품에 대해 2~4단계를 반복합니다.

작업 프로젝트 준비
Google Play Console에서 디지털 상품을 설정한 경우 작업 프로젝트를 Play 앱과 연결할 수 있습니다.
작업 프로젝트에서 디지털 상품 거래를 사용 설정하려면 다음 안내를 따르세요. 단계:
- Actions 콘솔에서 프로젝트를 열거나 새 프로젝트를 만듭니다.
- 배포, 디렉터리 정보로 차례로 이동합니다.
- 추가 정보 및 거래에서 예 체크박스를 선택합니다. 작업이 Digital Purchase API를 사용하여 거래를 수행하나요? 디지털 상품 판매
- 저장을 클릭합니다.
디지털 상품 API 키 만들기
디지털 상품 API에 요청을 보내려면 JSON 서비스를 다운로드해야 합니다. 작업 콘솔 프로젝트와 연결된 계정 키입니다.
서비스 계정 키를 가져오려면 다음 단계를 따르세요.
- Actions 콘솔에서 오른쪽 상단에 있는 점 3개 아이콘을 클릭합니다. 프로젝트 설정을 클릭합니다.
- 작업의 프로젝트 ID를 찾습니다.
- 이 링크를 따라 '<project_id>'을(를) 대체 를 프로젝트 ID로 바꿉니다.https://console.developers.google.com/apis/credentials?project=project_id
- 기본 탐색 메뉴에서 사용자 인증 정보로 이동합니다.
- 표시되는 페이지에서 사용자 인증 정보 만들기를 클릭한 다음 서비스를 클릭합니다. 계정 키를 선택합니다.
- 서비스 계정으로 이동하고 새 서비스 계정을 클릭합니다.
- 서비스 계정에 디지털 트랜잭션과 같은 이름을 지정합니다.
- 만들기를 클릭합니다.
- 역할을 프로젝트 > 소유자를 선택합니다.
- 계속을 클릭합니다.
- 키 만들기를 클릭합니다.
- JSON 키 유형을 선택합니다.
- 키 만들기를 클릭하고 JSON 서비스 계정 키를 다운로드합니다.
이 서비스 계정 키를 안전한 장소에 저장하세요. 이 키는 fulfillment를 사용하여 디지털 구매 API의 클라이언트를 만듭니다.
Play 인벤토리에 연결
Actions 프로젝트에서 디지털 상품에 액세스하려면 프로젝트를 연결된 속성을 참조하세요.
참고: 확인 절차를 완료하는 데 최대 일주일이 걸릴 수 있습니다. 설정할 수 있습니다 이 기간이 지나도 웹사이트 또는 앱이 연결되지 않으면 지원팀에 문의하세요.
Play Console 웹 도메인 및 앱을 작업 프로젝트에 연결하려면 다음 단계를 따르세요. 다음 단계를 따르세요.
- Actions 콘솔에서 배포로 이동한 다음 브랜드 확인으로 이동합니다.
- 속성을 연결하지 않은 경우 먼저 웹사이트를 연결하세요. - 웹 속성 (</>) 버튼을 클릭합니다.
- 웹 도메인의 URL을 입력하고 연결을 클릭합니다.
 - Google은 계정에 가입해야 하는 개인에게 추가 안내가 포함된 이메일을 확인된 사용자 인증 정보는 Google Search Console 이 이메일의 수신자가 위의 단계를 따르면 웹사이트에서 브랜드 인증 아래에 표시됩니다. 
- 연결된 웹사이트가 하나 이상 있으면 다음 단계를 따르세요. Android 앱을 연결합니다. - Actions 콘솔에서 배포로 이동한 다음 브랜드 확인으로 이동합니다.
- 앱 연결을 클릭합니다.
- 표시되는 페이지에서 안내에 따라 웹을 인증합니다. Play Console에서 도메인을 확인하세요. 앱이 포함된 Play 앱을 선택합니다. URL을 입력합니다. 브랜드 확인 페이지. - Google은 다시 한번 확인 이메일을 않습니다. 관리자가 인증을 승인하면 Play 앱에서 다음을 완료해야 합니다. 브랜드 인증 아래에 표시됩니다. 
- Play 구매 항목에 액세스를 사용 설정합니다. 
 

구매 흐름 구축하기
작업 프로젝트와 디지털 상품 인벤토리가 준비된 상태에서 디지털 상품을 빌드하세요. 제품 구매 흐름을 통합할 수 있습니다
1. 디지털 구매 API 클라이언트 설정
대화 처리 웹훅에서 서비스로 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. 정보 수집
사용자가 구매하기 전에 작업은 어떤 상품을 구매할 수 있는지 있습니다.
2. a. 거래 요구사항 확인
사용자의 계정이 Google의 개인 정보 보호 장치를
구매를 선택할 수 있습니다. 이 단계
사용자가 결제 수단을 설정했고
해당 언어로 번역됩니다. 거래 시작 시
흐름에서 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. b. 사용 가능한 인벤토리 수집
디지털 구매 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 도우미 인텐트를
광고 항목을 표시합니다.
다음 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. 결과 처리
구매가 완료되면 actions_intent_COMPLETE_PURCHASE이 트리거됩니다.
Dialogflow 이벤트 (또는 actions.intent.COMPLETE_PURCHASE Actions SDK 인텐트)와
결과를 설명하는 COMPLETE_PURCHASE_VALUE 인수 인텐트를 빌드하고
이벤트를 통해 트리거되어 사용자에게 결과를 전달합니다.
다음과 같은 구매 결과를 처리합니다.
- PURCHASE_STATUS_OK: 구매가 완료되었습니다. 거래 이 시점에서 완료된 상태이므로 트랜잭션 흐름을 종료하고 대화를 나누는 것입니다.
- PURCHASE_STATUS_ALREADY_OWNED: 사용자가 님이 이미 해당 항목을 소유하고 있습니다. 사용자의 이전 질문을 확인하여 이 오류를 방지하세요. 표시되지 않도록 맞춤 설정할 수 있습니다. 이미 갖고 있는 상품을 재구매할 가능성이 높습니다.
- PURCHASE_STATUS_ITEM_UNAVAILABLE: 요청한 항목이 없습니다. 이 오류를 방지하려면 사용 가능한 구매 시점이 가까워진 SKU
- PURCHASE_STATUS_ITEM_CHANGE_REQUESTED: 사용자가 다른 것을 구매하기로 결정했습니다. 주문 생성으로 다시 메시지 표시 사용자가 즉시 다른 결정을 내릴 수 있습니다.
- PURCHASE_STATUS_USER_CANCELLED: 사용자가 구매 흐름을 취소했습니다. 사용자가 흐름을 너무 일찍 종료했으므로 사용자가 트랜잭션을 다시 시도하거나 트랜잭션을 종료하려는 경우 완전히 달라졌습니다.
- PURCHASE_STATUS_ERROR: 알 수 없는 이유로 거래에 실패했습니다. Google 사용자가 거래가 실패했음을 알고 다시 시도할지 묻습니다.
- 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));
    });
  });
});
사용자의 구매 반영
사용자가 작업을 쿼리하면 요청 JSON의 user 객체에 목록이 포함됩니다.
알 수 있습니다. 이 정보를 확인하고 작업의 응답을 변경하세요.
사용자가 지불한 콘텐츠에 따라 광고가 게재됩니다.
다음 샘플 코드는 다음과 같은 요청의 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"
        }
      ]
    }
  ],
  ...
}
