다음을 통해 공유


비영수증 결제 처리(레거시 경제)

Important

Economy v1 API는 유지 관리 모드에 있으며 새로운 기능은 제공되지 않으며 버그 수정만 제공됩니다. v1 API는 당분간 유지될 것입니다. PlayFab Economy의 다음 버전에 대해 자세히 알아보려면 Economy v2 개요를 참조하세요!

다양한 플랫폼에서의 영수증 검증 외에도, PlayFab은 영수증 또는 권한 기반 시스템을 사용하지 않는 결제 서비스 공급자를 통해 구매할 수 있도록 하는 PlayFab 메커니즘을 제공합니다. 여기에는 Facebook, PayPal, Xsolla 및 Steam과 같은 공급자가 포함됩니다.

이 자습서에서는 이 카트 스타일 결제 시스템 사용을 설명하고 다음에 대한 방법을 보여 줍니다.

  • 플레이어가 구입하기 원하는 재화 세트를 정의합니다.

  • 선택된 제공자로 플레이어를 처리합니다.

  • 결제가 성공적으로 처리되었는지를 검증하고, 해당 아이템을 플레이어의 인벤토리에 추가합니다.

  • 또한 이 자습서에서는 프로세스 가운데 플레이어 공급자 부분을 다루며 구매 완료까지의 전체 개요를 안내합니다.

다음 이미지는 결제 흐름에서 사용되는 API 호출의 요약을 보여 줍니다.

PlayFab - 결제 API 흐름

결제 제공자 설정

실제로 결제를 처리하기 위한 로직을 시작하기 전에 가장 먼저 해야할 일은 이용하려는 결제 서비스 공급자를 실제로 설정하는 것입니다.

그렇게 하려면:

  • PlayFab 게임 관리자에서 게임을 선택합니다.
  • 추가 기능 탭을 선택합니다.

그러면 추가 기능 마켓플레이스로 이동되어, 귀하는 결제 제공자를 포함하여 우리의 모든 제3자 통합을 확인할 수 있습니다.

참고 항목

Facebook 및 Steam 같은 일부 제공자는 단순히 결제를 취급하는 것보다 ‘더 많은’ 일을 하는 데 귀하는 그것을 이 자습서의 플랫폼 섹션에서 확인할 수 있습니다.

  • 사용하기 원하는 제공자를 선택합니다.
  • 이어서 각각을 위한 설치 옵션을 선택합니다.
  • 요청된 정보(일반적으로 애플리케이션 및 비밀 키)를 입력하지만 각 제공자는 고유한 요건을 갖고 있을 것입니다.

참고 항목

이 정보로 우리는 귀하를 대신하여 그들의 서비스와 통신할 수 있기 때문에 우리는 구매를 개시시키고 그 상태를 체크할 수 있습니다.

  • 그것이 완료되면 귀하는 결제 흐름 구현을 시작할 준비가 됩니다.

PlayFab API 호출

이 프로세스를 위한 클라이언트 측의 호출 순서는 대부분의 비영수증 결제 서비스 공급자의 순서와 비슷합니다.

  • StartPurchase - 구매를 위한 재화의 목록을 만듭니다.
  • PayForPurchase - 결제 제공자를 확립하고 결제 가격을 잠급니다.
  • ConfirmPurchase - 구매가 성공적으로 완료되었는지를 검증하고, 필요한 경우 재화가 플레이어의 인벤토리에 추가되도록 합니다.

참고 항목

이에 대한 예외는 Xsolla로서, 이 자습서 말미에 별도로 설명되어 있습니다.

다음 예에서는 {{TitleID}}{{SessionTicket}}과(와) 같은 필드가 표시됩니다. 귀하의 코드에 있는 이러한 값을 게임을 위한 적절한 값과 플레이어 인증 티켓으로 교체해야 합니다.

구매 개시

구매 흐름 전반에 걸쳐 귀하는 게임 카탈로그 가운데 플레이어가 구입하려는 정의된 제품 세트로 작업합니다.

이것이 재화 카트인데, PlayFab 클라이언트 API 메서드 StartPurchase를 호출하여 정의함으로써 프로세스를 시작합니다.

PlayFabClientAPI.StartPurchase(new StartPurchaseRequest() {
    CatalogVersion = "IAP1_0",
    Items = new List<ItemPurchaseRequest>() {
        new ItemPurchaseRequest() {
            ItemId = "BigBagOfGold",
            Quantity = 1,
            Annotation = "Purchased via in-game store"
        }
    }
}, result => {
    // Handle success
}, error => {
    // Handle error
});

이 예에서 우리는 게임 카탈로그에 ID가 IAP1_0 - BigBagOfGold로 정의된 아이템으로 카트를 채우고 있습니다. 이것이 게임 카탈로그에 정의된 ItemId입니다.

플레이어가 이 가운데 하나만 구매하려고 합니다. 주석을 통해 아이템이 플레이어 인벤토리에 어떻게 저장되었는지가 표시되고, 이는 이후 검토에 유용하게 쓰이게 됩니다.

참고 항목

StoreId 매개 변수를 포함함으로써 이 구매가 귀하가 게임에 정의한 Store 가격 책정을 사용하고 있음을 명시할 수 있습니다.

StartPurchase 호출의 반환은 귀하의 카탈로그 아이템에 대한 DisplayNameDescription 값, 정의된 가격 및 플레이어의 가상 통화 잔액을 포함한 많은 정보를 포함합니다.

그러나 다음 단계에 필요한 주요 사항은 OrderId(이 구매를 고유하게 식별함)와 PaymentOptions에서 귀하가 사용하기 원하는 특정 제공자입니다.

참고 항목

귀하의 타이틀을 위해 활성화한 결제 제공자만 PaymentOptions에 나타날 것입니다.

{
  "code": 200,
  "status": "OK",
  "data": {
    "OrderId": "1234567890ABCDEF",
    "Contents": [{
      "ItemId": "BigBagOfGold",
      "ItemInstanceId": "ABCDEF1234567890",
      "DisplayName": "A hefty sack of gold",
      "Description": "Why, it’s a stonking great bag of shiny!",
      "VirtualCurrencyPrices": {
        "RM": 999
      }
    }],
    "PaymentOptions": [{
        "Currency": "RM",
        "ProviderName": "Facebook",
        "Price": 999,
        "StoreCredit": 0
      },
      {
        "Currency": "RM",
        "ProviderName": "PayPal",
        "Price": 999,
        "StoreCredit": 0
      },
      {
        "Currency": "RM",
        "ProviderName": "Steam",
        "Price": 999,
        "StoreCredit": 0
      }
    ],
    "VirtualCurrencyBalances": {
      "VC": 0
    }
  }
}

결제 제공자 확립: 웹후크 제공자

Facebook

일반적으로 이 시점의 흐름은 어떤 결제 서비스 공급자를 사용할지 PlayFab에 알려줍니다. 이는 서비스에서 해당 공급자와 통신하고 트랜잭션에 대한 정보를 설정할 수 있도록 하기 위한 것입니다.

이 절차에 대한 예외는 Facebook입니다. Facebook은 구매가 ‘먼저’ ‘그들의’ 서비스에서 개시될 것을 요구합니다. 그 후 PlayFab 같은 제3자 서비스가 Facebook 제공 거래 식별자를 사용하여 구매 상태를 확인할 수 있습니다.

귀하의 Store, 카탈로그 또는 아이템 ID가 영숫자가 ‘아닌’ 경우, OpenGraphProduct URL을 구축할 때는 다음 코드처럼 HTML / URL 인코딩이어야 합니다.

FB.ui({
    method: 'pay',
    action: 'purchaseitem',
    product: "https://{{TitleId}}.playfabapi.com/OpenGraphProduct/{{TitleId}}/{{StoreId}}/IAP1_0/BigBagOfGold",
    request_id: "1234567890ABCDEF"
}, function (response) {
    console.log('Payment completed', response);
    print(response);
    if (response.payment_id) {
        facebookPurchaseId = response.payment_id;
        payForOrder(); // This is a function call you need to write
                       // which makes the call to the Client API PayForPurchase
                       // (see below)
    }
});

이 호출을 할 때 Facebook에서는 제품이 ‘대/소문자 구분’임을 기억하세요.

특히, PlayFab에서는 귀하의 게임을 위해 ‘올바른’ 타이틀 ID로 교체해야 하는 TitleId는 일반적으로 해당 서비스에서 소문자입니다. Facebook에서 올바른 제품을 찾지 못하는 문제가 발생하는 경우에는 이 페이지의 설명처럼 GET 요청을 사용하여 제품을 수동으로 잡아보세요.

그뿐만 아니라, 흐름에서 이전 값을 사용하고 있는지 확인할 필요도 있습니다.

  • 구입할 아이템이 들어 있는 PlayFab 정의 카탈로그의 CatalogID(IAP1_0)

  • 구입할 게임의 PlayFab 카탈로그에 있는 아이템의 itemID(BigBagOfGold)

  • 이 프로세스를 시작할 때 StartPurchase 호출에서 반환된 OrderID(1234567890ABCDEF)

대응이 성공적인 경우, Facebook이 payment_id을(를) 반환하고, 이는 클라이언트 API 메서드 PayForPurchase 호출에서 ProviderTransactionId(으)로 사용될 수 있습니다.

const string paymentId = "_SOME_PAYMENT_ID" ;
PlayFabClientAPI.PayForPurchase(new PayForPurchaseRequest() {
    OrderId = "1234567890ABCDEF",
    ProviderName = "Facebook",
    Currency = "RM",
    ProviderTransactionId = paymentId
}, result => {
    // Handle success
}, error => {
    // Handle error
});

이렇게 하면 간단한 확인이 반환됩니다.

{
    "code": 200,
    "status": "OK",
    "data": {
        "OrderId": "1234567890ABCDEF",
        "Status": "Init",
        "PurchaseCurrency": "RM",
        "PurchasePrice": 999,
        "CreditApplied": 0
    }
}

이것으로 PlayFab을 등식의 양쪽에서 구매에 연결하는 고리가 완성되어 우리는 그 상태를 질의할 수 있습니다.

Facebook 개발자 포털에서 Facebook 결제 시스템에 대한 자세한 설명을 읽을 수 있습니다. https://developers.facebook.com/docs/payments/overview

Facebook 결제의 또 다른 측면은 결제 상태의 실시간 변경 알림을 활성화하려면 타이틀이 결제용 웹후크를 사용해야 한다는 점입니다.

Facebook 모델에서는 어떤 경우에 결제 완료에 시간이 매우 오래 걸릴 수 있기 때문에 이것이 필요합니다. 다행히 이것은 간단합니다. Facebook의 타이틀 설정에서 다음을 귀하의 콜백 URL로 입력합니다.

https://{{TitleId}}.playfabapi.com/ThirdPartyPayments/FacebookPaymentUpdate

여기서 {{TitleId}}는 PlayFab에서 귀하의 게임을 위한 타이틀 ID입니다(예: https://aaa.playfabapi.com/ThirdPartyPayments/FacebookPaymentUpdate).

Facebook 설정에서 토큰을 지정할 필요는 없습니다. 콜백 URL을 설정하고, 게임 관리자Facebook 추가 기능 페이지에서 귀하의 PlayFab 설정이 올바른지 확인만 하면 됩니다.

Facebook에서 이 웹후크를 사용하여 결제 상태를 업데이트할 때 주문 상태가 PlayFab에서 업데이트됩니다. 성공하면 적절한 아이템이 플레이어 인벤토리에 추가됩니다.

참고 항목

보안: 이 API는 PlayFab으로 하여금 Facebook을 다시 호출하여 거래를 안전하게 인증 및 검증하도록 하는 프롬프트가 됩니다. 해커가 Facebook 결제를 우회하기 위한 뒷문이 아닙니다.

결제 서비스 공급자로 Facebook을 사용할 때 여기에서 보여주듯 고객의 구매 확인이 여전히 중요합니다.

결제 제공자 확립: 비웹후크 제공자

Steam

Steam은 ‘모든’ 결제 제공자들 중에서 통합하기가 가장 쉽습니다.

PlayFabClientAPI.PayForPurchase(new PayForPurchaseRequest() {
    OrderId = "1234567890ABCDEF",
    ProviderName = "Steam",
    Currency = "RM"
}, result => {
    // Handle success
}, error => {
    // Handle error
});

PayForPurchase 호출의 결과로 PlayFab은 Steam이 제공하는 웹 메서드를 사용하여 해당 서비스에서 구매를 개시합니다. 그러면 사용자에게는 Steam 클라이언트를 통해 구매 확인 대화상자가 표시됩니다.

따라서 클라이언트 API PayForPurchase 호출의 반응을 받는 동시에 사용자에게 결제를 수락하라는 메시지가 표시됩니다.

{
    "code": 200,
    "status": "OK",
    "data": {
        "OrderId": "1234567890ABCDEF",
        "Status": "Init",
        "PurchaseCurrency": "RM",
        "PurchasePrice": 999,
        "CreditApplied": 0
    }
}

Steam은 콜백 메커니즘을 사용하여 타이틀에 구매 프로세스 완료를 알려주므로 MicroTxnAuthorizationResponse_t 콜백을 위해서는 콜백 처리기를 등록해야 합니다.

등록된 Steam 개발자는 다음 위치에서 이 프로세스에 대한 상세 정보를 받을 수 있습니다. https://partner.steamgames.com/documentation/MicroTxn#WebPurchasing.

콜백을 받으면 타이틀이 마지막 단계: 구매 확정 섹션에 보이는 ConfirmPurchase 호출을 진행합니다.

PayPal

PayPal의 경우 PayForPurchase 호출은 사실상 Steam과 동일합니다.

PlayFabClientAPI.PayForPurchase(new PayForPurchaseRequest() {
    OrderId = "1234567890ABCDEF",
    ProviderName = "PayPal",
    Currency = "RM"
}, result => {
    // Handle success
}, error => {
    // Handle error
});

단, 이 경우에는 플레이어에게 결제 요청을 보내는 편리한 클라이언트 애플리케이션이 없습니다.

PayPal에서는 플레이어에게 PayPal 인터페이스를 제시하여, 구매에 동의하는지 확인을 요청할 필요가 있습니다. 그러나 우리가 모든 세부 사항을 처리하기 때문에 그 배후에서 이 프로세스는 PayPal 익스프레스 체크아웃을 사용합니다.

귀하는 사용자에게 결제 확인 페이지를 제시하기만 하면 되며, 그것은 귀하에게 PurchaseConfirmationPageURL로 반환됩니다.

{
    "code": 200,
    "status": "OK",
    "data": {
        "OrderId": "1234567890ABCDEF",
        "Status": "Init",
        "PurchaseCurrency": "RM",
        "PurchasePrice": 999,
        "PurchaseConfirmationPageURL": "https://...",
        "CreditApplied": 0
    }
}

이 경우에는 일단 브라우저 창이 해제되면 이로써 PlayFab에서 구매 확인으로 이동할 때임을 나타냅니다.

마지막 단계: 구매 확인

프로세스의 최종 부분은 PlayFab이 구매한 아이템(있는 경우)을 플레이어의 인벤토리에 추가하여 구매 프로세스를 완료하는 것입니다.

일부 공급자의 경우 이 단계에서 구매가 성공적으로 완료되었는지 여부를 이미 타이틀에서 압니다.

어떤 경우든 클라이언트 API 메서드 ConfirmPurchase 호출은 결제는 되었지만 아이템이 아직 추가되지 않은 경우에만 플레이어 인벤토리에 아이템을 추가합니다.

PlayFabClientAPI.ConfirmPurchase(new ConfirmPurchaseRequest() {
    OrderId = "1234567890ABCDEF"
}, result => {
    // Handle success
}, error => {
    // Handle error
});

이 시점에서 주문이 성공적으로 완료되면 우리는 귀하가 설정한 카트에서 클라이언트 API StartPurchase를 호출하여 아이템을 반복합니다.

그러면 플레이어의 인벤토리에 아이템이 추가되고 아이템에 대한 정보가 타이틀에 반환됩니다.

{
    "code": 200,
    "status": "OK",
    "data": {
        "OrderId": "1234567890ABCDEF",
        "Status": "Succeeded",
        "PurchaseDate": "2016-07-19T09:04:28Z",
        "Items": [{
            "ItemId": "BigBagOfGold",
            "ItemInstanceId": "ABCDEF1234567890",
            "CatalogVersion": "IAP1_0",
            "DisplayName": "A hefty sack of gold",
            "UnitCurrency": "RM",
            "UnitPrice": 999
        }]
    }
}

거래 상태

막후에는 주문이 거치게 되는 많은 상태 변화가 있습니다. 전체 목록은 아래에 제공됩니다.

참고 항목

특정 공급자 프로세스에 따라 이들 상태 중 일부는 세 가지 구매 프로세스 API 호출 중 어느 것의 결과에도 나타나지 않으며, 여기에서는 온전성을 위해 포함하였습니다.

  • CreateCart - 주문 개체 자체가 클라이언트 API StartPurchase에 대한 응답에서 반환되지 않지만, 그 시점에 생성은 되었습니다. 이 단계에서는 아이템과 가격이 개체에 저장되지만 결제 서비스 공급자에게 제출되지는 않았습니다.

  • Init - 주문이 결제 서비스 공급자에게 제출되었지만 제공자가 아직 승인하지 않은 경우 반환되는 상태입니다.

  • Approved - 플레이어가 결제를 승인한 직후, PlayFab이 플레이어 인벤토리에 아이템을 배치하는 프로세스를 완료하기 전에 발생합니다. 이 상태에서는 타이틀이 주문을 볼 수 없으며, 이 목록에는 온전성을 위해 포함되었을 뿐입니다.

  • Succeeded - 주문이 성공적으로 완료되었음을 나타냅니다. 플레이어가 결제를 승인하였고, 해당 플레이어 인벤토리에 모든 인벤토리 아이템이 추가되었습니다.

  • FailedByProvider - 어떤 이유로든 제공자가 결제를 거부하는 경우(플레이어가 결제를 거절하는 경우 포함), 주문은 제공자가 불합격시킨 것으로 간주됩니다.

  • DisputePending - 결제 제공자가 PlayFab에 미해결 결제 분쟁을 알렸습니다.

  • RefundPending - 결제 제공자가 PlayFab에 환불 요청이 발행되었음을 알렸습니다. 이 단계에서 환불은 실제로 발생되지 않았습니다.

  • - 주문이 환불되었습니다. 대부분(전부는 아니라도), 결제 제공자는 이 정보를 바로 개발자에게도 제공합니다. 이 상태는 아이템이 소모성 제품(이미 소비되었을 수 있음)인지 여부와 같은 여러 요인에 따라 달라질 수 있습니다.

  • RefundFailed - 환불이 요청되었지만 결제 제공자가 거부했습니다. PlayFab은 이에 대한 추가 정보를 제공할 수 없으므로 자세한 설명이 필요한 경우 개발자가 직접 결제 서비스 공급자에게 문의해야 합니다.

  • ChargedBack - 이 상태는 결제 제공자별로 다르며, 주문이 분쟁 속에 있거나 또는 다시 청구되었음을 표시할 수 있습니다. 역시, 주문 내역에 대한 상세 정보는 결제 제공자에게 문의해야 합니다.

  • FailedByPlayFab - 이 상태는 결제 프로세스에서 예상치 못한 실패가 발생했음을 나타냅니다. 이 상태 반응을 보는 즉시 타이틀은 이전의 결제 API 호출을 다시 시도해야 합니다. 이 상태가 계속되면, 당사의 지원 포럼에 이 문제를 게시하고 문제와 관련된 모든 세부 사항(타이틀 ID, PlayFab ID, 주문 ID)을 제공하는 것이 좋습니다.

Xsolla를 이용한 결제의 수락

Xsolla의 경우는 프로세스가 다릅니다. 위의 코드 흐름을 사용하지 않고, 여기 https://developers.xsolla.com/doc/in-game-store/extensions/playfab-integration/에서 설명하는 Xsolla 결제 흐름을 사용합니다.

Xsolla 결제 서비스를 사용하려면 귀하의 타이틀을 구성하기 위해 Xsolla의 가맹점 ID, 프로젝트 ID 및 가맹점 API 키가 필요합니다.

  • 시작하려면 추가 기능 마켓플레이스의 Xsolla 페이지의 링크를 사용하여 Xsolla 계정을 신청하세요.

  • 해당 구성 페이지가 설정되면 다음 단계는 Xsolla 서비스에서 재화 카탈로그를 만드는 것입니다.

  • Xsolla의 각 항목에 대한 item_code가 PlayFab 카탈로그의 항목 ID와 일치하는지 확인합니다. 이는 구매를 완료하고 플레이어 인벤토리에 올바른 항목을 안전하게 추가하는 데 사용하는 식별자입니다.

  • Xsolla 카탈로그에 가상 아이템 목록을 설정하려면 앞서 이 지침에서 제공한 Xsolla 설명서를 참조하세요.

구매 개시(Xsolla)

구매 준비가 완료되면 GetPaymentToken API 호출을 사용하고 TokenProvider(으)로 지정하여 Xsolla 서비스에 토큰을 요청합니다.

PlayFabClientAPI.GetPaymentToken(new GetPaymentTokenRequest() {
    TokenProvider = "xsolla"
}, result => {
    // Handle success
}, error => {
    // Handle error
});

호출은 ProviderToken을 반환할 것이고, 그것은 Xsolla 토큰으로서 그 다음 단계에서 PlayFab OrderId과(와) 함께 필요합니다. 막후에서 이 호출은 Xsolla와의 거래를 개시합니다.

{
    "code": 200,
    "status": "OK",
    "data": {
        "ProviderToken": "1234567890ABCDEF",
        "OrderId": "1234567890ABCDEF"
    }
}

구매 완료(Xsolla)

그런 다음, 클라이언트는 결제 프로세스를 시작하기 위해 토큰을 Xsolla에 전달해야 합니다. 다음 URL 중 하나를 사용하여 Xsolla에 해당 토큰을 전달할 수 있습니다:

샌드박스 결제:

https://sandbox-secure.xsolla.com/paystation3/?access_token=[TOKEN]

라이브 결제:

 https://secure.xsolla.com/paystation3/?access_token=[TOKEN]

이 작업을 수행한 후에는 Xsolla 인터페이스에서 구매를 완료할 수 있습니다.

인터페이스 사용에 대한 궁금한 사항 역시 앞서 이 지침에서 제공한 링크의 Xsolla 설명서를 참조하세요.

그것이 완료되면 귀하가 취할 조치는 더 이상 없습니다. Xsolla와 PlayFab은 웹후크 호출을 교환합니다. PlayFab은 구매된 아이템을 플레이어 인벤토리에 넣음으로써 구매를 끝내고 PlayStream에 적절한 이벤트를 게시합니다.

클라이언트 API GetPurchase 호출을 폴링하여 거래 상태를 확인할 수 있습니다(위의 전체 목록 참조).

대부분의 경우 이 프로세스는 2-3초 이내에 끝납니다.

PlayFabClientAPI.GetPurchase(new GetPurchaseRequest()
{
    OrderId = "1234567890ABCDEF"
}, result =>
{
    // Handle success
}, error =>
{
    // Handle error
});
{
    "code": 200,
    "status": "OK",
    "data": {
        "OrderId": "1234567890ABCDEF",
        "PaymentProvider": "Xsolla",
        "TransactionStatus": "Succeeded",
        "PurchaseDate": "2017-06-07T00:00:00Z"
    }
}

최종 노트

알고 있어야 하는 한 가지는 일부 제공자의 경우 결제가 완료되는 데 긴 시간이 걸릴 수 있다는 것입니다.

클라이언트 API ConfirmPurchase 호출의 응답에서 구매 상태가 아직도 Init인 경우, 기다렸다가 다시 쿼리해야 합니다. 여기에서의 모범 사례는 프로세스 시작 시점에서 OrderId을(를) 저장한 다음, 결과를 쿼리할 때 지수 백오프를 사용하는 것입니다.

따라서 상태가 Init인 경우 1분 기다린 후에 클라이언트 API ConfirmPurchase 호출을 다시 시도한 다음, 2분 기다리고, 그 다음 4, 8분 등으로 최대값에 도달할 때까지 기다립니다. check for completed transactions(완료된 거래 체크) 옵션을 포함하는 것은 사용자가 그 타이머를 리셋하는 방법을 제공할 것입니다.

마지막으로, 일부 결제 제공자의 경우 구매를 테스트하기 위해 샌드박스 모드를 사용할 수 있음도 주목할만 합니다.

그렇게 하려면, PlayFab 게임 관리자의 타이틀의 추가 기능 탭에서 Use sandbox purchase testing(샌드박스 구매 테스트 사용) 옵션을 선택하세요.