Google Play 결제를 통해 Digital Goods API 및 Payment Request API로 결제 받기

안드레 치프리아니 반다라
앙드레 치프리아니 반다라

앱이 Google Play를 통해 배포되며 디지털 상품을 판매하거나 정기 결제를 제공하려면 Google Play 결제를 사용해야 합니다. Google Play 결제는 카탈로그, 가격 및 정기 결제, 유용한 보고서, 사용자에게 이미 익숙한 Play 스토어에서 제공하는 결제 흐름을 관리하는 도구를 제공합니다.

신뢰할 수 있는 웹 활동을 사용하여 빌드하고 Google Play 스토어를 통해 제공되는 앱의 경우 이제 Payment Request APIDigital Goods API를 사용하여 Google Play 결제와 통합할 수 있습니다. Android 및 ChromeOS용 Chrome 101 이상에서 사용할 수 있습니다.

이 가이드에서는 Google Play 결제 지원을 PWA에 추가하고 ChromeOS와 Play 스토어 모두에서 Google Play 스토어에서 배포할 수 있도록 패키징하는 방법을 알아봅니다.

2개의 웹 플랫폼 API를 사용하여 PWA에 Play 결제 지원을 추가합니다. Digital Goods API는 SKU 정보를 수집하고 Play 스토어에서 구매 및 사용 권한을 확인하는 데 사용됩니다. Payment Request API는 Google Play 스토어를 결제 수단으로 구성하고 구매 흐름을 완료하는 데 사용됩니다.

Play 스토어에서 애플리케이션으로 수익을 창출하는 방법

애플리케이션에서 Google Play 결제를 사용하여 Play 스토어에서 수익을 창출하는 방법에는 두 가지가 있습니다.

  • 인앱 구매를 사용하면 추가 기능 또는 광고 삭제와 같은 내구재와 소비성 가상 상품을 모두 판매할 수 있습니다.
  • 정기 결제는 사용자가 뉴스 구독 또는 멤버십과 같은 정기 결제를 통해 콘텐츠나 서비스에 지속적으로 액세스할 수 있도록 합니다.

요구사항

Google Play 결제를 설정하려면 다음이 필요합니다.

Bubblewrap 프로젝트 업데이트

Bubblewrap이 설치되어 있지 않으면 설치해야 합니다. 시작하는 방법에 관한 자세한 내용은 빠른 시작 가이드를 참고하세요. 이미 Bubblewrap이 있는 경우 버전 1.8.2 이상으로 업데이트해야 합니다.

Bubblewrap에는 깃발 뒤에 있는 기능도 있습니다. 이 기능을 사용 설정하려면 프로젝트 루트에 있는 twa-manifest.json에서 프로젝트 구성을 수정하고 alphaDependenciesplayBilling 기능을 모두 사용 설정해야 합니다.

  ...,
  "enableNotifications": true,
  "features": {
    "playBilling": {
      "enabled": true
    }
  },
  "alphaDependencies": {
    "enabled": true
  },
  ...

구성 파일이 업데이트되면 bubblewrap update를 실행하여 프로젝트에 구성을 적용하고 bubblewrap build를 실행하여 새 Android 패키지를 생성하고 이 패키지를 Play 스토어에 업로드합니다.

Digital Goods API 및 Google Play 결제 사용 가능 여부 감지 기능

Digital Goods API는 현재 신뢰할 수 있는 웹 활동 내에서 PWA가 실행되는 경우에만 Chrome에서 지원되며 window 객체에서 getDigitalGoodsService를 확인하여 사용 가능 여부를 감지할 수 있습니다.

if ('getDigitalGoodsService' in window) {
 // Digital Goods API is supported!
}

Digital Goods API는 모든 브라우저에서 사용할 수 있으며 다양한 스토어를 지원합니다. 특정 매장 백엔드가 지원되는지 확인하려면 매장 ID를 매개변수로 전달하는 getDigitalGoodsService()를 호출해야 합니다. Google Play 스토어는 https://play.google.com/billing 문자열로 식별됩니다.

if ('getDigitalGoodsService' in window) {
  // Digital Goods API is supported!
  try {
    const service =
        await window.getDigitalGoodsService('https://play.google.com/billing');
    // Google Play Billing is supported!

  } catch (error) {
    // Google Play Billing is not available. Use another payment flow.
    return;
  }
}

SKU 세부정보 가져오기

Digital Goods API는 결제 백엔드에서 제품 제목, 설명, 가장 중요한 가격 등의 정보를 검색할 수 있는 getDetails()를 제공합니다.

그런 다음 사용 인터페이스에서 이 정보를 사용하여 사용자에게 세부정보를 제공할 수 있습니다.

const skuDetails = await service.getDetails(['shiny_sword', 'gem']);
for (item of skuDetails) {
  // Format the price according to the user locale.
  const localizedPrice = new Intl.NumberFormat(
      navigator.language,
      {style: 'currency', currency: item.price.currency}
    ).format(item.price.value);

  // Render the price to the UI.
  renderProductDetails(
        item.itemId, item.title, localizedPrice, item.description);
}

구매 흐름 빌드

PaymentRequest의 생성자는 결제 수단 목록과 결제 세부정보 목록이라는 두 가지 매개변수를 사용합니다.

신뢰할 수 있는 웹 활동 내에서 https://play.google.com/billing를 식별자로 설정하고 제품 SKU를 데이터 멤버로 추가하여 Google Play 결제 수단을 사용해야 합니다.

async function makePurchase(service, sku) {
   // Define the preferred payment method and item ID
   const paymentMethods = [{
       supportedMethods: "https://play.google.com/billing",
       data: {
           sku: sku,
       }
   }];

   ...
}

결제 세부정보가 필요하지만 Play 결제는 이러한 값을 무시하고 Play Console에서 SKU를 만들 때 설정된 값을 사용하므로 가짜 값으로 채워질 수 있습니다.

const paymentDetails = {
    total: {
        label: `Total`,
        amount: {currency: `USD`, value: `0`}
    }
};

const request = new PaymentRequest(paymentMethods, paymentDetails);

결제 요청 객체에서 show()를 호출하여 결제 흐름을 시작합니다. 프로미스가 성공하면 결제가 성공했을 수 있습니다. 실패하면 사용자가 결제를 취소했을 가능성이 높습니다.

프로미스가 성공하면 구매를 확인하고 확인해야 합니다. 사기를 방지하려면 이 단계는 백엔드를 사용하여 구현해야 합니다. 백엔드에서 인증을 구현하는 방법은 Play 결제 문서를 참고하세요. 구매를 확인하지 않으면 3일 후 사용자가 환불을 받고 Google Play에서 구매를 취소합니다.

...
const request = new PaymentRequest(paymentMethods, paymentDetails);
try {
    const paymentResponse = await request.show();
    const {purchaseToken} = paymentResponse.details;

    // Call backend to validate and acknowledge the purchase.
    if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) {
        // Optional: tell the PaymentRequest API the validation was
        // successful. The user-agent may show a "payment successful"
        // message to the user.
        const paymentComplete = await paymentResponse.complete('success');
    } else {
        // Optional: tell the PaymentRequest API the validation failed. The
        // user agent may show a message to the user.
        const paymentComplete = await paymentResponse.complete('fail');
    }
} catch(e) {
    // The purchase failed, and we can handle the failure here. AbortError
    // usually means a user cancellation
}
...

원하는 경우 purchaseToken에서 consume()를 호출하여 구매를 소진된 것으로 표시하고 다시 구매할 수 있습니다.

종합하면 구매 메서드는 다음과 같습니다.

async function makePurchase(service, sku) {
    // Define the preferred payment method and item ID
    const paymentMethods = [{
        supportedMethods: "https://play.google.com/billing",
        data: {
            sku: sku,
        }
    }];

    // The "total" member of the paymentDetails is required by the Payment
    // Request API, but is not used when using Google Play Billing. We can
    // set it up with bogus details.
    const paymentDetails = {
        total: {
            label: `Total`,
            amount: {currency: `USD`, value: `0`}
        }
    };

    const request = new PaymentRequest(paymentMethods, paymentDetails);
    try {
        const paymentResponse = await request.show();
        const {purchaseToken} = paymentResponse.details;

        // Call backend to validate and acknowledge the purchase.
        if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) {
            // Optional: consume the purchase, allowing the user to purchase
            // the same item again.
            service.consume(purchaseToken);

            // Optional: tell the PaymentRequest API the validation was
            // successful. The user-agent may show a "payment successful"
            // message to the user.
            const paymentComplete =
                    await paymentResponse.complete('success');
        } else {
            // Optional: tell the PaymentRequest API the validation failed.
            // The user agent may show a message to the user.
            const paymentComplete = await paymentResponse.complete('fail');
        }
    } catch(e) {
        // The purchase failed, and we can handle the failure here.
        // AbortError usually means a user cancellation
    }
}

기존 구매 상태 확인

Digital Goods API를 사용하면 다른 기기, 이전 설치, 프로모션 코드 사용, 앱을 마지막으로 연 시점 등 사용자가 이미 구매한 이전 구매의 기존 사용 권한 (아직 소비되지 않은 인앱 구매 또는 진행 중인 정기 결제)이 있는지 확인할 수 있습니다.


const service =
     await window.getDigitalGoodsService('https://play.google.com/billing');
...
const existingPurchases = await service.listPurchases();
for (const p of existingPurchases) {
    // Update the UI with items the user is already entitled to.
    console.log(`Users has entitlement for ${p.itemId}`);
}

이전에 구매했지만 아직 확인하지 않은 구매가 있는지 확인하는 것도 좋습니다. 사용자의 사용 권한이 앱에 제대로 반영되도록 가능한 한 빨리 구매를 확인하는 것이 좋습니다.

const service =
     await window.getDigitalGoodsService("https://play.google.com/billing");
...
const existingPurchases = await service.listPurchases();
for (const p of existingPurchases) {
    await verifyOrAcknowledgePurchaseOnBackend(p.purchaseToken, p.itemId);

    // Update the UI with items the user is already entitled to.
    console.log(`Users has entitlement for ${p.itemId}`);
}

통합 테스트

개발 중인 Android 기기에서

Android 개발 기기에 Digital Goods API를 테스트용으로 사용 설정할 수 있습니다.

  • 개발자 모드를 사용 설정한 상태에서 Android 9 이상을 사용 중인지 확인합니다.
  • Chrome 101 이상을 설치합니다.
  • chrome://flags로 이동하고 플래그 이름으로 검색하여 Chrome에서 다음 플래그를 사용 설정합니다.
    • #enable-debug-for-store-billing
  • 사이트가 https 프로토콜을 사용하여 호스팅되는지 확인합니다. http를 사용하면 API가 undefined이 됩니다.

ChromeOS 기기에서

Digital Goods API는 버전 89부터 ChromeOS 공개 버전에서 사용할 수 있습니다. 그동안 Digital Goods API를 테스트할 수 있습니다.

  • 기기의 Play 스토어에서 앱을 설치합니다.
  • 사이트가 https 프로토콜을 사용하여 호스팅되는지 확인합니다. http를 사용하면 API가 undefined이 됩니다.

테스트 사용자 및 품질보증팀과 함께 활용

Play 스토어는 사용자 테스트 계정 및 테스트 SKU를 포함하여 테스트를 위한 어포던스를 제공합니다. 자세한 내용은 Google Play 결제 테스트 문서를 참고하세요.

다음 단계

이 문서에서 설명한 것처럼 Play Billing API에는 Digital Goods API에서 관리하는 클라이언트 측 구성요소와 서버 측 구성요소가 있습니다.