Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
Android 인앱 구매
Godot는 Google Play 결제 라이브러리 <https://developer.android.com/google/play/billing>`_를 사용하는 Godot 4.2+와 호환되는 자사 ``GodotGooglePlayBilling` Android 플러그인을 제공합니다.
사용례
시작하기
Android Gradle Builds <doc_android_gradle_build>`을 활성화하고 성공적으로 설정했는지 확인하세요. ``GodotGooglePlayBilling` `github 페이지 <https://github.com/godotengine/godot-google-play-billing>`__의 설치 지침을 따르세요.
패키지 설치하기
GodotGooglePlayBilling API를 사용하려면:
``BillingClient``에 액세스합니다.
연결를 시그널로 전송하여 청구 결과를 수신합니다.
연결(Connections)
초기화 예시:
var billing_client: BillingClient
func _ready():
billing_client = BillingClient.new()
billing_client.connected.connect(_on_connected) # No params
billing_client.disconnected.connect(_on_disconnected) # No params
billing_client.connect_error.connect(_on_connect_error) # response_code: int, debug_message: String
billing_client.query_product_details_response.connect(_on_query_product_details_response) # response: Dictionary
billing_client.query_purchases_response.connect(_on_query_purchases_response) # response: Dictionary
billing_client.on_purchase_updated.connect(_on_purchase_updated) # response: Dictionary
billing_client.consume_purchase_response.connect(_on_consume_purchase_response) # response: Dictionary
billing_client.acknowledge_purchase_response.connect(_on_acknowledge_purchase_response) # response: Dictionary
billing_client.start_connection()
API를 사용하려면 먼저 연결된 상태여야 합니다. 연결 프로세스가 성공하면 connected 시그널가 전송됩니다. is_ready()``를 사용하여 플러그인을 사용할 준비가 되었는지 확인할 수도 있습니다. ``get_connection_state() 함수는 플러그인의 현재 연결 상태를 반환합니다.
``get_connection_state()``의 반환 값:
# Matches BillingClient.ConnectionState in the Play Billing Library.
# Access in your script as: BillingClient.ConnectionState.CONNECTED
enum ConnectionState {
DISCONNECTED, # This client was not yet connected to billing service or was already closed.
CONNECTING, # This client is currently in process of connecting to billing service.
CONNECTED, # This client is currently connected to billing service.
CLOSED, # This client was already closed and shouldn't be used again.
}
6 가지 패턴 유형이 있습니다:
API가 연결되면 query_product_details()`를 사용하여 제품 ID를 쿼리합니다. ``purchase()`, purchase_subscription() 또는 update_subscription() 함수를 호출하기 전에 제품 세부 정보 쿼리를 성공적으로 완료해야 합니다. 그렇지 않으면 오류가 반환됩니다. query_product_details()``는 제품 ID 문자열 배열과 쿼리되는 제품 유형이라는 두 가지 매개변수를 사용합니다. 제품 유형은 일반 인앱 구매의 경우 ``BillingClient.ProductType.INAPP, 구독의 경우 ``BillingClient.ProductType.SUBS``여야 합니다. 배열의 ID 문자열은 앱의 Google Play Console 항목에 정의된 제품 ID와 일치해야 합니다.
StaticBody2D 이용 예시:
func _on_connected():
billing_client.query_product_details(["my_iap_item"], BillingClient.ProductType.INAPP) # BillingClient.ProductType.SUBS for subscriptions.
func _on_query_product_details_response(query_result: Dictionary):
if query_result.response_code == BillingClient.BillingResponseCode.OK:
print("Product details query success")
for available_product in query_result.product_details:
print(available_product)
else:
print("Product details query failed")
print("response_code: ", query_result.response_code, "debug_message: ", query_result.debug_message)
사용자 구매 쿼리
사용자의 구매 항목을 검색하려면 제품 유형을 쿼리에 전달하는 query_purchases() 함수를 호출하세요. 제품 유형은 일반 인앱 구매의 경우 BillingClient.ProductType.INAPP, 구독의 경우 BillingClient.ProductType.SUBS``여야 합니다. ``query_purchases_response 시그널가 결과와 함께 전송됩니다. 시그널에는 응답 코드와 구매 배열 또는 디버그 메시지가 포함된 :ref:`Dictionary <class_Dictionary>`라는 단일 매개 변수가 있습니다. 활성 구독과 사용되지 않은 일회성 구매만 구매 배열에 포함됩니다.
StaticBody2D 이용 예시:
func _query_purchases():
billing_client.query_purchases(BillingClient.ProductType.INAPP) # Or BillingClient.ProductType.SUBS for subscriptions.
func _on_query_purchases_response(query_result: Dictionary):
if query_result.response_code == BillingClient.BillingResponseCode.OK:
print("Purchase query success")
for purchase in query_result.purchases:
_process_purchase(purchase)
else:
print("Purchase query failed")
print("response_code: ", query_result.response_code, "debug_message: ", query_result.debug_message)
아이템 구매
항목에 대한 청구 흐름을 시작하려면: 인앱 제품에 대해 ``purchase()``를 사용하고 제품 ID 문자열을 전달합니다. 구독에는 ``purchase_subscription()``를 사용하여 제품 ID와 기본 요금제 ID를 전달하세요. 선택적으로 제안 ID를 제공할 수도 있습니다.
purchase() 및 purchase_subscription() 모두 선택적으로 부울을 전달하여 제안이 `개인화 <https://developer.android.com/google/play/billing/integrate#personalized-price>`_인지 여부를 나타낼 수 있습니다.
알림: 항목을 ``purchase()``에 전달하기 전에 반드시 항목에 대한 제품 세부 정보를 쿼리해야 합니다. 이 메소드는 청구 흐름이 성공적으로 시작되었는지 여부를 나타내는 사전을 반환합니다. 여기에는 응답 코드와 구매 배열 또는 디버그 메시지가 포함됩니다.
StaticBody2D 이용 예시:
var result = billing_client.purchase("my_iap_item")
if result.response_code == BillingClient.BillingResponseCode.OK:
print("Billing flow launch success")
else:
print("Billing flow launch failed")
print("response_code: ", result.response_code, "debug_message: ", result.debug_message)
구매 결과는 on_purchases_updated 시그널를 통해 전송됩니다.
func _on_purchases_updated(result: Dictionary):
if result.response_code == BillingClient.BillingResponseCode.OK:
print("Purchase update received")
for purchase in result.purchases:
_process_purchase(purchase)
else:
print("Purchase update error")
print("response_code: ", result.response_code, "debug_message: ", result.debug_message)
처리 순서
query_purchases_response 및 on_purchases_updated 시그널는 Dictionary 형식으로 다양한 구매 항목을 제공합니다. 구매 사전에는 Google Play Billing Purchase 클래스의 값에 매핑되는 키가 포함되어 있습니다.
구매 분야:
order_id: String
purchase_token: String
package_name: String
purchase_state: int
purchase_time: int (milliseconds since the epoch (Jan 1, 1970))
original_json: String
is_acknowledged: bool
is_auto_renewing: bool
quantity: int
signature: String
product_ids: PackedStringArray
구매 상태 확인
구매가 완료되었는지 또는 아직 보류 중인지 확인하려면 구매의 purchase_state 값을 확인하세요.
구매 상태 값:
# Matches Purchase.PurchaseState in the Play Billing Library
# Access in your script as: BillingClient.PurchaseState.PURCHASED
enum PurchaseState {
UNSPECIFIED,
PURCHASED,
PENDING,
}
구매가 PENDING 상태인 경우 PURCHASED 상태에 도달할 때까지 구매 내용을 부여하거나 추가 구매 처리를 수행해서는 안 됩니다. 스토어 인터페이스가 있는 경우 Google Play 스토어에서 완료해야 하는 보류 중인 구매에 대한 정보를 표시할 수 있습니다. 대기 중인 구매에 대한 자세한 내용은 Google Play 결제 라이브러리 문서의 `대기 중인 거래 처리 <https://developer.android.com/google/play/billing/integrate#pending>`_를 참조하세요.
상수
인앱 아이템이 일회성 구매가 아니고 여러 번 구매할 수 있는 소모성 아이템(예: 코인)인 경우 구매 사전의 purchase_token 값을 전달하여 consume_purchase()``를 호출하여 아이템을 소비할 수 있습니다. ``consume_purchase()``로 전화하면 자동으로 구매가 승인됩니다. 제품을 소비하면 사용자가 해당 제품을 다시 구매할 수 있으며, 재구매하지 않는 한 후속 ``query_purchases() 호출에 더 이상 표시되지 않습니다.
StaticBody2D 이용 예시:
func _process_purchase(purchase):
if "my_consumable_iap_item" in purchase.product_ids and purchase.purchase_state == BillingClient.PurchaseState.PURCHASED:
# Add code to store payment so we can reconcile the purchase token
# in the completion callback against the original purchase
billing_client.consume_purchase(purchase.purchase_token)
func _on_consume_purchase_response(result: Dictionary):
if result.response_code == BillingClient.BillingResponseCode.OK:
print("Consume purchase success")
_handle_purchase_token(result.token, true)
else:
print("Consume purchase failed")
print("response_code: ", result.response_code, "debug_message: ", result.debug_message, "purchase_token: ", result.token)
# Find the product associated with the purchase token and award the
# product if successful
func _handle_purchase_token(purchase_token, purchase_successful):
# check/award logic, remove purchase from tracking list
구매 확인
인앱 항목이 일회성 구매인 경우 acknowledge_purchase() 함수를 호출하고 구매 사전에서 purchase_token 값을 전달하여 구매를 확인해야 합니다. 3일 이내에 구매를 확인하지 않으면 사용자는 자동으로 환불을 받고 Google Play에서는 구매를 취소합니다. ``comsume_purchase()``로 전화하면 자동으로 구매가 승인되므로 ``acknowledge_purchase()``로 전화할 필요가 없습니다.
StaticBody2D 이용 예시:
func _process_purchase(purchase):
if "my_one_time_iap_item" in purchase.product_ids and \
purchase.purchase_state == BillingClient.PurchaseState.PURCHASED and \
not purchase.is_acknowledged:
# Add code to store payment so we can reconcile the purchase token
# in the completion callback against the original purchase
billing_client.acknowledge_purchase(purchase.purchase_token)
func _on_acknowledge_purchase_response(result: Dictionary):
if result.response_code == BillingClient.BillingResponseCode.OK:
print("Acknowledge purchase success")
_handle_purchase_token(result.token, true)
else:
print("Acknowledge purchase failed")
print("response_code: ", result.response_code, "debug_message: ", result.debug_message, "purchase_token: ", result.token)
# Find the product associated with the purchase token and award the
# product if successful
func _handle_purchase_token(purchase_token, purchase_successful):
# check/award logic, remove purchase from tracking list
설명
구독은 대부분 일반 인앱 항목처럼 작동합니다. 구독 세부 정보를 얻으려면 ``BillingClient.ProductType.SUBS``를 ``query_product_details()``의 두 번째 인수로 사용하세요. 구독 구매 세부정보를 얻으려면 ``BillingClient.ProductType.SUBS``를 ``query_purchases()``에 전달하세요.
``query_purchases()``에서 반환된 구독 구매에서 ``is_auto_renewing``를 확인하여 사용자가 자동 갱신 구독을 취소했는지 확인할 수 있습니다.
새로운 구독 구매를 확인해야 하지만 자동 구독 갱신은 인정하지 않습니다.
다양한 구독 수준 간 업그레이드 또는 다운그레이드를 지원하는 경우 update_subscription()``를 사용하여 구독 업데이트 흐름을 사용하여 활성 구독을 변경해야 합니다. ``purchase()``와 마찬가지로 결과는 ``on_purchases_updated 시그널에 의해 반환됩니다. ``update_subscription()``의 매개변수는 다음과 같습니다.
old_purchase_token: 현재 활성 구독의 구매 토큰
replacement_mode: 구독에 적용할 대체 모드
product_id: 전환할 새 구독의 제품 ID
base_plan_id: 대상 구독의 기본 계획 ID
Offer_id: 기본 요금제의 제안 ID(선택 사항)
is_offer_personalized: 개인화된 가격 책정 활성화 여부(선택 사항)
대체 모드 값은 다음과 같이 정의됩니다.
# Access in your script as: BillingClient.ReplacementMode.WITH_TIME_PRORATION
enum ReplacementMode {
# Unknown...
UNKNOWN_REPLACEMENT_MODE = 0,
# The new plan takes effect immediately, and the remaining time will be prorated and credited to the user.
# Note: This is the default behavior.
WITH_TIME_PRORATION = 1,
# The new plan takes effect immediately, and the billing cycle remains the same.
CHARGE_PRORATED_PRICE = 2,
# The new plan takes effect immediately, and the new price will be charged on next recurrence time.
WITHOUT_PRORATION = 3,
# Replacement takes effect immediately, and the user is charged full price of new plan and
# is given a full billing cycle of subscription, plus remaining prorated time from the old plan.
CHARGE_FULL_PRICE = 5,
# The new purchase takes effect immediately, the new plan will take effect when the old item expires.
DEFERRED = 6,
}
기본 동작은 ``WITH_TIME_PRORATION``입니다.
StaticBody2D 이용 예시:
billing_client.update_subscription(_active_subscription_purchase.purchase_token, \
BillingClient.ReplacementMode.WITH_TIME_PRORATION, "new_sub_product_id", "base_plan_id")