모바일 SDK를 통한 구매 버튼 활성화
중요한 이유

최근 특정 지역 내 Apple 정책의 업데이트에 따라, 이제 개발자는 사용자가 앱에서 외부 웹 사이트로 이동하여 가상 아이템을 결제하도록 유도할 수 있습니다.
Apple의 규정 위반이나 단속 위험 없이 클릭 한 번으로 사용자를 게임에서 안전 브라우저 기반의 체크아웃(웹샵 솔루션 또는 결제 UI)으로 바로 이동시켜 아이템을 구매할 수 있게 돕는 버튼, 배너, 메시지 및 기타 콜 투 액션을 추가할 수 있습니다.
게임에서 미리 구축된 아이템별 결제 페이지로 연결하고 결제 흐름을 더 효과적으로 통제하고자 할 경우 모바일 SDK를 통한 구매 버튼 통합이 이상적입니다. 여기에는 다음과 같은 장점들이 있습니다.
- 구매 경험의 유연한 사용자 지정(거래 로직부터 시각적 표현까지)
- 서버리스 설정 지원(SDK는 백엔드 없이도 작동할 수 있음. 구매 및 아이템 전달이 클라이언트 측에서 처리되므로 웹훅이 필요 없음)
- 다양한 결제 방법(Apple Pay를 통한 원클릭 결제 등, 신속하고 친숙한 모바일 결제 경험을 제공)
Xsolla 모바일 SDK를 통한 통합은 웹 사이트 빌더를 기반으로 하지 않는 맞춤형 웹샵 솔루션을 사용 중이며 게임에 바로 페이 스테이션을 통합하고자 하는 경우에 적합합니다.
가장 신속한 로우코드 통합 옵션을 원한다면 웹샵 솔루션 기반 통합을 확인해 보세요.
작동 방식
이 가이드에서는 Apple의 요구 사항에 따라 엑솔라 모바일 SDK를 사용하여 결제를 처리하기 위해 엑솔라를 통합하는 방법을 배웁니다.
Apple의 요구 사항:
외부 구매를 위한 인앱 WebViews는 허용되지 않습니다. Safari 또는 기본 브라우저를 통해 결제해야 합니다.
외부 구매 링크는 현재 미국 스토어프론트에서 iOS 애플리케이션에 대해서만 허용됩니다. Apple의 앱 검토 가이드라인은
사용자 위치가 아닌 미국 스토어프론트 를 기준으로 한다는 점에 유의하세요.
사용자 절차:
- 사용자가 iOS에서 게임 애플리케이션을 엽니다.
- 사용자가 원하는 아이템 바로 옆에 있는 구매 버튼을 클릭합니다.
- 애플리케이션이 결제 토큰이 포함된 페이 스테이션 링크가 있는 Safari(또는 기본 브라우저)를 엽니다. SDK가 인증 및 아이템 선택을 처리합니다.
- 사용자가 자동으로 승인됩니다. 특정 아이템에 대한 페이 스테이션이 열립니다.
- 사용자가 결제 방법을 선택하고 구매를 완료합니다.
- 페이 스테이션이 사용자를 게임 애플리케이션으로 리디렉션합니다.
- 애플리케이션은 웹훅을 통해 구매 확인을 받습니다.
빠른 시작
관리자 페이지 가입 및 프로젝트 생성
관리자 페이지는 엑솔라 기능을 구성하고 분석과 트랜잭션 작업에 사용하는 기본 도구입니다.
가입하려면 관리자 페이지로 이동하여 계정을 생성합니다. 프로젝트를 만들려면 사이드 메뉴에서 프로젝트 생성을 클릭하고 필요한 정보를 입력합니다. 설정은 나중에 수정할 수 있습니다.

연동을 처리하는 동안 프로젝트 이름 옆의 관리자 페이지에서 확인할 수 있는 프로젝트 ID를 제공해야 합니다.

엑솔라 로그인 설정
- 관리자 페이지의 프로젝트에서 플레이어 > 로그인 섹션으로 이동합니다.
- 로그인 프로젝트 생성을 클릭합니다.
- 표준 로그인 프로젝트를 선택하고 생성 및 설정을 클릭합니다. 새 로그인 프로젝트가 생성될 때까지 기다립니다. 그러면 로그인 프로젝트 페이지가 표시됩니다.
- 로그인 메서드 블록에서 옵션을 선택하고 구성 을 클릭합니다 .
- 상단 설정 블록에서 로그인 API 통합 을 클릭합니다 .
- 장치 ID로 로그인 토글을 켜짐으로 설정합니다.

- 변경 사항 저장을 클릭합니다.
연동을 진행하는 동안 로그인 ID가 필요합니다. 로그인 ID를 구하려면 사이트 이동 경로에서 로그인 프로젝트의 이름을 클릭한 후 로그인 프로젝트 페이지로 돌아가서 로그인 프로젝트 이름 옆의 ID 복사를 클릭합니다.

인앱 구매 제품(가상 아이템) 구성
다음 방법 중 하나를 선택하여 IAP SKU 제품 카탈로그를 설정합니다.
SDK 설치
엑솔라 모바일 SDK는 XCFramework
named XsollaMobileSDK.xcframework
로 제공됩니다.
Xcode 프로젝트에 수동으로 설치하는 방법:
- Xcode에서 프로젝트를 엽니다.
- 앱 대상을 선택하고 General 탭으로 이동합니다.
- Frameworks, Libraries, and Embedded Content 섹션에,
XsollaMobileSDK.xcframework
파일을 가져다 놓습니다. - 프레임워크 옆의 드롭다운 목록에서, Embed & Sign을 선택합니다.

SDK 구성
SDK 구성을 위해서는 관리자 페이지의 다음 ID가 필요합니다.
- 프로젝트 ID. 프로젝트 이름 옆의 관리자 페이지에서 찾을 수 있습니다.
- 로그인 ID. 액세스하려면 관리자 페이지를 열고 플레이어 > 로그인 > 대시보드 > 로그인 프로젝트 섹션으로 이동하고 로그인 프로젝트 이름 옆의 ID 복사를 클릭합니다.
시작점으로 예제 ID를 사용할 수 있습니다.
settings.openExternalBrowser = YES;
(Objective-C) 또는 settings.openExternalBrowser = true;
(Swift)를 SDK 구성에 추가합니다.obj-c
- obj-c
- swift
1#import <XsollaMobileSDK/StoreKitWrapper.h>
2
3SKPaymentSettings* settings = [[SKPaymentSettings alloc] initWithProjectId: 77640
4 loginProjectId:@"026201e3-7e40-11ea-a85b-42010aa80004"
5 platform: SKPaymentPlatformStandalone
6 paystationUIThemeId: SKPaystationThemeDark
7 paystationUISize: SKPaystationSizeMedium];
8
9settings.useSandbox = YES;
10settings.enablePayments = YES;
11settings.openExternalBrowser = YES;
12
13SKPaymentQueue* queue = [SKPaymentQueue defaultQueue];
14[queue startWithSettings: settings];
15[queue addTransactionObserver: self];
1import XsollaMobileSDK
2
3let settings = SKPaymentSettings(projectId: 77640,
4 loginProjectId: "026201e3-7e40-11ea-a85b-42010aa80004",
5 platform: .standalone)
6
7settings.useSandbox = true;
8settings.enablePayments = true;
9settings.openExternalBrowser = true;
10
11SKPaymentQueue.default().start(settings)
12SKPaymentQueue.default().add(self)
구매 후 사용자를 게임 앱으로 돌아가도록 딥링킹 구성
대상에 대한 URL 구조 설정:
- 프로젝트 탐색기에서 프로젝트를 선택합니다.
- 대상을 선택합니다.
- Info 탭을 엽니다.
- URL Types 섹션에서 ➕ 버튼을 클릭합니다.
- URL Scheme를
$(PRODUCT_BUNDLE_IDENTIFIER)
로 설정합니다.

SDK 초기화
구성 후 엑솔라 모바일 SDK를 초기화하고 엑솔라 서비스에 연결해야 합니다. 이 로직을 앱의 초기화 절차(예: AppDelegate의 didFinishLaunchingWithOptions 메서드 내부)에 배치하세요.
obj-c
- obj-c
- swift
1SKPaymentQueue* queue = [SKPaymentQueue defaultQueue];
2[queue startWithSettings: settings]; // settings from the previous step
3
4// conform your class to SKPaymentTransactionObserver and implement its method
5@interface YourClass (SKPaymentTransactionObserver) <SKPaymentTransactionObserver>
6@end
7
8@implementation YourClass (SKPaymentTransactionObserver)
9
10- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
11 for(SKPaymentTransaction *transaction in transactions) {
12 switch (transaction.transactionState) {
13 case SKPaymentTransactionStateFailed:
14 // purchase failed, present an error
15 break;
16 case SKPaymentTransactionStatePurchased:
17 // award the player with the purchase of the SKU - transaction.payment.productIdentifier
18 break;
19 default: break;
20 }
21 }
22}
23
24@end
1SKPaymentQueue.default().start(settings)
2SKPaymentQueue.default().add(self)
3
4// conform your class to SKPaymentTransactionObserver and implement its method
5extension YourClass: SKPaymentTransactionObserver {
6 func paymentQueue(_: SKPaymentQueue, updatedTransactions: [SKPaymentTransaction]) {
7 for transaction in updatedTransactions {
8 switch transaction.transactionState {
9 case .failed:
10 // purchase failed, present an error
11 case .purchased:
12 // award the player with the purchase of the SKU - transaction.payment.productIdentifier
13 default:
14 break
15 }
16 }
17 }
18}
SKPaymentQueue
를 시작하고 트랜잭션 옵저버를 추가한 후 애플리케이션은 다음과 같이 SKU 정보를 요청할 수 있습니다.
obj-c
- obj-c
- swift
1NSSet *skus = [NSSet setWithArray:@[@"your_sku1", @"your_sku2"]];
2SKProductsRequest* req = [[SKProductsRequest alloc] initWithProductIdentifiers:skus];
3
4req.delegate = self;
5[req start];
6
7// conform your class to SKProductsRequestDelegate and implement its method
8@interface YourClass (SKProductsRequestDelegate) <SKProductsRequestDelegate>
9@end
10
11@implementation YourClass (SKProductsRequestDelegate)
12
13- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
14 // save loaded products somewhere
15 self.products = response.products
16}
17
18@end
1let skus: Set<String> = ["your_sku1", "your_sku2"]
2let req = SKProductsRequest(productIdentifiers: skus)
3
4req.delegate = self
5req.start()
6
7// conform your class to SKProductsRequestDelegate and implement its method
8extension YourClass: SKProductsRequestDelegate {
9 func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
10 // save loaded products somewhere
11 self.products = response.products
12 }
13}
구매하기
구매 절차는 다단계 공정으로, 결제 수집, 구매 유효성 검사, 사용과 관련이 있습니다.
구매 절차 시작
결제를 생성하고 구매를 시작하려면 이전에 획득한 SKProduct
정보를 사용합니다.
obj-c
- obj-c
- swift
1SKProduct *product = ...; // previously fetched product
2SKPayment *payment = [SKPayment paymentWithProduct:product];
3[[SKPaymentQueue defaultQueue] addPayment:payment];
1let product = ... // previously fetched product
2let payment = SKPayment(product: product)
3SKPaymentQueue.default().add(payment)
구매 유효성 검사
무단 구매를 방지하는 데 도움이 되도록 각 구매는 최종 사용자에게 전달하기 전에 유효성 검사해야 합니다.
구매의 유효성을 보장하는 가장 효과적인 방법은 서버-서버(S2S) 호출을 사용하여 의사 결정 프로세스에서 클라이언트를 제거함으로써 잠재적인 보안 허점이 발생하지 않도록 하는 것입니다.
일반적으로 S2S 유효성 검사 접근 방식은 다음 단계를 따르십시오.
- 애플리케이션 클라이언트는 구매 주문 ID를 백엔드로 전송합니다. 이 ID는 클라이언트 측에서 결제 거래가 완료될 때 일반적으로 거래 콜백을 통해 받습니다. 구매가 시작되는 방법에 대한 내용을 보려면 구매 절차 시작을 참조합니다.
- 서버는 구매 후 서버 알림을 받는 즉시 엑솔라 서비스에 의해 트리거 된 웹훅 방식을 사용하여 주문 ID를 수신하고 진위 여부를 검증합니다. 이를 통해 폴링에 의존하지 않고 비동기로 영수증을 처리할 수 있으며 클라이언트의 요청이 들어오기도 전에 결과가 캐시되어 백그라운드에서 수행될 수도 있습니다. 웹훅에 대한 자세한 내용은 웹훅 설정하기 섹션을 참조합니다.
구매한 콘텐츠 사용
구매 절차 체인의 맨 마지막 단계는 사용자에게 구매를 수여하고 해당 구매를 ‘수여됨’으로 표시하는 것입니다. 이 프로세스를 “구매 사용"이라고도 합니다.
구매 결과는 Objective-C로 되어 있는 paymentQueue:updatedTransactions:
콜백 또는 Swift로 되어 있는 paymentQueue(_:updatedTransactions:)
콜백을 통해 전달됩니다.
obj-c
- obj-c
- swift
1- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
2 for(SKPaymentTransaction *transaction in transactions) {
3 switch (transaction.transactionState) {
4 case SKPaymentTransactionStateFailed:
5 // Always acknowledge transaction and finish it
6 [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
7 break;
8 case SKPaymentTransactionStatePurchased:
9 // here you can save the purchase and award it to the user
10 // Always acknowledge transaction and finish it after it was saved
11 [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
12 break;
13 default: break;
14 }
15 }
16}
1func paymentQueue(_: SKPaymentQueue, updatedTransactions: [SKPaymentTransaction]) {
2 for transaction in updatedTransactions {
3 switch transaction.transactionState {
4 case .failed:
5 // Always acknowledge transaction and finish it
6 SKPaymentQueue.default().finishTransaction(transaction)
7 case .purchased:
8 // here you can save the purchase and award it to the user
9 // Always acknowledge transaction and finish it after it was saved
10 SKPaymentQueue.default().finishTransaction(transaction)
11 default:
12 break
13 }
14 }
15}
웹훅 설정
웹훅은 시스템에서 발생하는 이벤트에 대한 알림입니다. 특정 이벤트가 발생하면 엑솔라는 HTTP 요청을 전송하며, 이때 이벤트 데이터를 게임 서버로 전송합니다. 이러한 웹훅은 게임 클라이언트 및/또는 서버가 결제 및 사용자 인증 시도의 성공 및 실패에 대한 알림을 수신하기 위해 필수입니다.
웹훅 사용 방법
- 관리자 페이지의 프로젝트에서 프로젝트 설정 > 웹훅 솔루션 섹션으로 이동합니다.
- 웹훅 서버 필드에서
https://example.com
형식으로 웹훅을 수신할 서버 URL을 지정합니다. 웹훅 테스트용 도구에서 찾은 URL을 지정할 수도 있습니다. - 프로젝트 웹훅에 서명하기 위한 비밀 키가 기본적으로 생성됩니다. 새 비밀 키를 생성하려면 새로 고침 아이콘을 클릭합니다.
- 웹훅 사용을 클릭합니다.

웹훅 테스트 방법
결제 및 스토어 탭에서 다음 웹훅을 테스트할 수 있습니다.
사용자 유효성 검사(“notification_type”:“user_validation”):
- curl
1curl -v 'https://your.hostname/your/uri' \
2-X POST \
3-H 'Accept: application/json' \
4-H 'Content-Type: application/json' \
5-H 'Authorization: Signature 13342703ccaca5064ad33ba451d800c5e823db8f' \
6-d '{
7 "notification_type":"user_validation",
8 "settings": {
9 "project_id": 18404,
10 "merchant_id": 2340
11 },
12 "user": {
13 "ip": "127.0.0.1",
14 "phone": "18777976552",
15 "email": "email@example.com",
16 "id": "1234567",
17 "name": "John Smith",
18 "country": "US"
19 }
20}'
주문 결제 성공(“notification_type”: “order_paid”):
- curl
1curl -v 'https://your.hostname/your/uri' \
2-X POST \
3-H 'Accept: application/json' \
4-H 'Content-Type: application/json' \
5-H 'Authorization: Signature d09695066c52c1b8bdae92f2d6eb59f5b5f89843' \
6-d '{
7 "notification_type": "order_paid",
8 "items": [
9 {
10 "sku": "com.xsolla.item_1",
11 "type": "virtual_good",
12 "is_pre_order": false,
13 "quantity": 3,
14 "amount": "1000",
15 "promotions": [
16 {
17 "amount_without_discount": "6000",
18 "amount_with_discount": "5000",
19 "sequence": 1
20 },
21 {
22 "amount_without_discount": "5000",
23 "amount_with_discount": "4000",
24 "sequence": 2
25 }
26 ],
27 "custom_attributes":
28 {
29 "purchased": 0,
30 "attr": "value"
31 }
32 },
33 {
34 "sku": "com.xsolla.item_new_1",
35 "type": "bundle",
36 "is_pre_order": false,
37 "quantity": 1,
38 "amount": "1000",
39 "promotions": []
40 },
41 {
42 "sku": "com.xsolla.gold_1",
43 "type": "virtual_currency",
44 "is_pre_order": false,
45 "quantity": 1500,
46 "amount": null,
47 "promotions": []
48 }
49 ],
50 "order": {
51 "id": 1,
52 "mode": "default",
53 "currency_type": "virtual",
54 "currency": "sku_currency",
55 "amount": "2000",
56 "status": "paid",
57 "platform": "xsolla",
58 "comment": null,
59 "invoice_id": "1",
60 "promotions": [
61 {
62 "amount_without_discount": "4000",
63 "amount_with_discount": "2000",
64 "sequence": 1
65 }
66 ],
67 "promocodes": [
68 {
69 "code": "promocode_some_code",
70 "external_id": "promocode_sku"
71 }
72 ],
73 "coupons": [
74 {
75 "code": "WINTER2021",
76 "external_id": "coupon_sku"
77 }
78 ]
79 },
80 "user": {
81 "external_id": "id_xsolla_login_1",
82 "email": "gc_user@xsolla.com"
83 },
84 "billing": {
85 "notification_type": "payment",
86 "settings": {
87 "project_id": 18404,
88 "merchant_id": 2340
89 },
90 "purchase": {
91 "subscription": {
92 "plan_id": "b5dac9c8",
93 "subscription_id": "10",
94 "product_id": "Demo Product",
95 "date_create": "2014-09-22T19:25:25+04:00",
96 "date_next_charge": "2014-10-22T19:25:25+04:00",
97 "currency": "USD",
98 "amount": 9.99
99 },
100 "total": {
101 "currency": "USD",
102 "amount": 200
103 },
104 "promotions": [{
105 "technical_name": "Demo Promotion",
106 "id": 853
107 }],
108 "coupon": {
109 "coupon_code": "ICvj45S4FUOyy",
110 "campaign_code": "1507"
111 }
112 },
113 "transaction": {
114 "id": 1,
115 "external_id": 1,
116 "payment_date": "2014-09-24T20:38:16+04:00",
117 "payment_method": 1,
118 "payment_method_name": "PayPal",
119 "payment_method_order_id": 1234567890123456789,
120 "dry_run": 1,
121 "agreement": 1
122 },
123 "payment_details": {
124 "payment": {
125 "currency": "USD",
126 "amount": 230
127 },
128 "vat": {
129 "currency": "USD",
130 "amount": 0,
131 "percent": 20
132 },
133 "sales_tax": {
134 "currency": "USD",
135 "amount": 0,
136 "percent": 0
137 },
138 "direct_wht": {
139 "currency": "USD",
140 "amount": 0,
141 "percent": 0
142 },
143 "payout_currency_rate": "1",
144 "payout": {
145 "currency": "USD",
146 "amount": 200
147 },
148 "country_wht": {
149 "currency": "USD",
150 "amount": 2,
151 "percent": 10
152 },
153 "user_acquisition_fee": {
154 "currency": "USD",
155 "amount": 2,
156 "percent": 1
157 },
158 "xsolla_fee": {
159 "currency": "USD",
160 "amount": 10
161 },
162 "payment_method_fee": {
163 "currency": "USD",
164 "amount": 20
165 },
166 "repatriation_commission": {
167 "currency": "USD",
168 "amount": 10
169 }
170 }
171 }
172 ,
173 "custom_parameters": {
174 "parameter1": "value1",
175 "parameter2": "value2"
176 }
177}'
샌드박스에서 테스트
이 섹션에는 결제 테스트, 상세 로그 기록 활성화 및 기타 관련 작업을 위해 샌드박스 환경을 구성하는 방법을 보여주는 코드 스니펫과 예제가 포함되어 있습니다.
샌드박스 모드 사용 방법
obj-c
- obj-c
- swift
1SKPaymentSettings* settings = ...;
2
3settings.useSandbox = YES;
1let settings = SKPaymentSettings(...)
2
3settings.useSandbox = true
추가 로그 기록 방법
obj-c
- obj-c
- swift
1SKPaymentSettings* settings = ...;
2
3settings.logLevel = SKLogLevelDebug;
1let settings = SKPaymentSettings(...)
2
3settings.logLevel = .debug
테스트 카드
샌드박스 모드에서 결제를 시뮬레이션할 수 있는 카드 목록은 테스트 카드 목록 섹션을 참조합니다.
라이브 시작
- 라이선스 계약에 서명합니다. 이렇게 하려면 관리자 페이지에서 계약 및 세금 > 계약 섹션으로 이동하여 계약 양식을 작성합니다.
- SDK 구성 코드에서
sandbox
를false
로 설정합니다.
obj-c
- obj-c
- swift
1SKPaymentSettings* settings = ...;
2
3settings.useSandbox = NO;
4settings.logLevel = SKLogLevelError;
1let settings = SKPaymentSettings(...)
2
3settings.useSandbox = false
4settings.logLevel = .error
iOS 스토어프론트를 감지하는 방법
현재 iOS 스토어프론트를 판별하고 지역에 따라 SDK 기능을 조정하려면 다음 코드 스니펫을 사용하세요.
obj-c
- obj-c
- swift
1[SKPaymentQueue loadCurrentStorefrontCountryCodeWithCompletion:^(NSString* _Nullable countryCode) {
2 settings.enablePayments = countryCode && [countryCode isEqualToString:@"USA"];
3
4 [[SKPaymentQueue defaultQueue] startWithSettings:settings];
5}];
1SKPaymentQueue.loadCurrentStorefrontCountryCode { countryCode in
2 settings.enablePayments = countryCode == "USA"
3
4 SKPaymentQueue.default().start(settings)
5}
loadCurrentStorefrontCountryCode
메서드는 현재 스토어프론트의 세 글자 국가 코드를 비동기적으로 검색합니다. 이 정보를 사용하여 특정 지역에 대한 SDK 기능을 활성화하거나 비활성화할 수 있습니다.
또는 아래에 제시되어 있는 바와 같이 Apple의 기본 스토어front를 직접 사용할 수도 있습니다:
SKStorefront
구현은 피하는 것이 좋습니다. Apple의 공식 문서에 명시된 바와 같이 UI가 멈추고 사용자 환경이 저하될 수 있습니다.- swift
1let storefront = await Storefront.current
2let countryCode = storefront?.countryCode
3
4settings.enablePayments = countryCode == "USA"
5
6SKPaymentQueue.default().start(settings)
작동 방식
이 가이드에서는 Apple의 요구 사항에 따라 엑솔라 API를 사용하여 결제를 처리하기 위해 엑솔라를 통합하는 방법을 배웁니다.
Apple의 요구 사항:
외부 구매를 위한 인앱 WebViews는 허용되지 않습니다. Safari 또는 기본 브라우저를 통해 결제해야 합니다.
외부 구매 링크는 현재 미국 스토어프론트에서 iOS 애플리케이션에 대해서만 허용됩니다. Apple의 앱 검토 가이드라인은
사용자 위치가 아닌 미국 스토어프론트 를 기준으로 한다는 점에 유의하세요.
사용자 절차:
- 사용자가 iOS에서 게임 애플리케이션을 엽니다.
- 사용자가 원하는 아이템 바로 옆에 있는 구매 버튼을 클릭합니다.
- 애플리케이션이 결제 토큰이 포함된 페이 스테이션 링크가 있는 Safari(또는 기본 브라우저)를 엽니다.
- 특정 아이템을 위한 페이 스테이션이 열립니다.
- 사용자가 결제 방법을 선택하고 구매를 완료합니다.
- 페이 스테이션이 사용자를 게임 애플리케이션으로 리디렉션합니다.
- 애플리케이션은 웹훅을 통해 구매 확인을 받습니다.
빠른 시작
관리자 페이지 가입 및 프로젝트 생성
관리자 페이지는 엑솔라 기능을 구성하고 분석과 트랜잭션 작업에 사용하는 기본 도구입니다.
가입하려면 관리자 페이지로 이동하여 계정을 생성합니다. 프로젝트를 만들려면 사이드 메뉴에서 프로젝트 생성을 클릭하고 필요한 정보를 입력합니다. 설정은 나중에 수정할 수 있습니다.

연동을 처리하는 동안 프로젝트 이름 옆의 관리자 페이지에서 확인할 수 있는 프로젝트 ID를 제공해야 합니다.

인앱 구매 제품(가상 아이템) 구성
다음 방법 중 하나를 선택하여 IAP SKU 제품 카탈로그를 설정합니다.
- 아이템 가져오기 – JSON 파일을 업로드하여 관리자 페이지에 카탈로그를 빠르게 추가할 수 있습니다.
- 가상 아이템 및 인게임 재화 > 관리자 문서 섹션에서 API 호출을 사용하여 아이템 카탈로그를 생성합니다.
유니버설 링크 구성
유니버설 링크는 사용자 장치에 애플리케이션이 설치되어 있는 경우 애플리케이션에서, 애플리케이션이 설치되어 있지 않은 경우 브라우저에서 열리는https://your-site.com/your-game
과 같은 링크입니다.
유니버설 링크 구성 방법:
- 웹 사이트의 루트에 도메인 연결 파일을 추가합니다(예:
https://your-site.com/apple-app-site-association
). - Xcode 프로젝트에서,
Signing & Capabilities > Associated Domains 로 이동하고applinks:your-site.com
을 추가합니다.
구매 후 사용자를 게임 앱으로 돌아가도록 리디렉션 구성
- 관리자 페이지에서 프로젝트를 열고 결제 > 결제 인터페이스 > 설정 > 리디렉션 정책 섹션으로 이동합니다.
- URL 반환 필드에 사용자가 결제 후 리디렉션되는 URL 주소 또는 경로(딥링크)를 입력합니다. 이 URL은 유니버설 링크를 지원해야 합니다. 게임 모바일 앱에서 사용자 환경을 개선하려면 딥링크를 반환 URL로 지정하는 것이 좋습니다.
- 자동 리디렉션 조건 드롭다운 목록에서 필요한 조건을 선택합니다.
- 수동 리디렉션 조건 드롭다운 목록에서 없음 - 리디렉션하지 않음을 선택합니다.
- 저장을 클릭합니다.
iOS 스토어프론트 감지
외부 결제 시스템은 현재 미국에서만 허용됩니다. 미국 스토어에서 앱을 획득했는지 확인하려면 다음 코드를 사용하십시오.
- swift
1let storefront = await Storefront.current
2let countryCode = storefront?.countryCode
3
4settings.enablePayments = countryCode == "USA"
5
6SKPaymentQueue.default().start(settings)
loadCurrentStorefrontCountryCode
메서드는 현재 스토어프론트의 세 글자 국가 코드를 비동기적으로 검색합니다.
구매하기
애플리케이션의 서버 측에서 주문 생성
앱 클라이언트는 결제 토큰을 가져오기 위해 서버에 요청을 전송합니다.
- swift
1struct TokenRequest: Codable {
2 let sku: String
3 let userId: String
4}
5
6func fetchPaymentToken(for sku: String, userId: String, completion: @escaping (Result<String, Error>) -> Void) {
7 let req = TokenRequest(sku: sku, userId: userId)
8 guard let url = URL(string: "https://your-backend.com/xsolla/create_token") else { return }
9 var request = URLRequest(url: url)
10 request.httpMethod = "POST"
11 request.setValue("application/json", forHTTPHeaderField: "Content-Type")
12 request.httpBody = try? JSONEncoder().encode(req)
13 URLSession.shared.dataTask(with: request) { data, _, error in
14 if let error = error {
15 completion(.failure(error)); return
16 }
17 let token = try! JSONDecoder().decode([String: String].self, from: data!)["token"]!
18 completion(.success(token))
19 }.resume()
20}
엑솔라 측에서 사용자 및 아이템 데이터로 주문을 생성하려면 구매용 결제 토큰 생성 API 호출을 사용합니다. 이 방법을 사용하면 결제 토큰이 반환됩니다. 이 과정에서 결제 UI를 열어 결제를 진행해야 합니다. 샌드박스 모드를 사용하려면 토큰을 요청하기 위한 본문에 “sandbox”: true
매개 변수를 전달해야 합니다.
결제 UI 열기
다음 링크를 통해 브라우저에서 결제 UI를 열려면 토큰을 수령한 후 링크를 생성하십시오. https://secure.xsolla.com/paystation4/?token=TOKEN
. 여기에서 TOKEN
는 수령한 토큰입니다.
- swift
1func openPayStation(token: String) {
2 let urlString = "https://secure.xsolla.com/paystation4/?token=\(token)"
3 guard let url = URL(string: urlString) else { return }
4 UIApplication.shared.open(url, options: [:], completionHandler: nil)
5}
결제 프로세스를 테스트하려면 샌드박스 모드를 사용할 수 있습니다. 샌드박스 모드는 실제 결제 및 거부된 결제를 제외한 라이브 환경의 모든 기능을 지원하는 독립 실행형 환경입니다. 샌드박스 모드에서, 일회성 결제와 은행 카드 및 PayPal을 사용하여 저장한 결제 수단으로 결제를 테스트할 수 있습니다.
사용자를 앱으로 리디렉션
결제가 완료되면 유니버설 링크를 사용하여 사용자를 앱으로 리디렉션되도록 처리합니다. 리디렉션을 처리하려면 SceneDelegate
또는 AppDelegate
에서 다음 메서드를 구현하십시오.
- swift
1func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
2 guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
3 let url = userActivity.webpageURL,
4 url.host == "your-site.com",
5 url.path.starts(with: "/payment_callback_success") else { return }
6 // Extract parameters (e.g., status, transaction_id)
7 let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
8 let queryItems = components?.queryItems
9 let status = queryItems?.first { $0.name == "status" }?.value
10 handlePaymentResult(status: status)
11}
웹훅 설정
- 관리자 페이지의 프로젝트에서 프로젝트 설정 > 웹훅 솔루션 섹션으로 이동합니다.
- 웹훅 서버 필드에서
https://example.com
형식으로 웹훅을 수신할 서버 URL을 지정합니다. 웹훅 테스트용 도구에서 찾은 URL을 지정할 수도 있습니다. - 프로젝트 웹훅에 서명하기 위한 비밀 키가 기본적으로 생성됩니다. 새 비밀 키를 생성하려면 새로 고침 아이콘을 클릭합니다.
- 웹훅 사용을 클릭합니다.

인게임 스토어 및 결제 관리를 제대로 운영하려면 메인 웹훅 처리를 구현해야 합니다.
웹훅 이름 | 설명 |
---|---|
사용자 유효성 검사 > 사용자 유효성 검사(user_validation ) | 사용자가 게임에 등록되어 있는지 확인하기 위해 결제를 처리하는 여러 단계에서 전송됩니다. |
게임 서비스 > 결합된 웹훅 > 주문 결제 성공(order_paid ) | 여기에는 결제 데이터, 트랜잭션 세부 사항 및 구매한 아이템에 대한 정보가 포함되어 있습니다. 웹훅의 데이터를 사용하여 사용자에게 구매한 아이템을 추가합니다. |
게임 서비스 > 결합된 웹훅 > 주문 취소(order_canceled ) | 여기에는 취소된 결제 데이터, 트랜잭션 세부 사항 및 구매한 아이템에 대한 정보가 포함되어 있습니다. 웹훅의 데이터를 사용하여 구매한 아이템을 제거합니다. |
런칭
- 라이선스 계약에 서명합니다. 이렇게 하려면 관리자 페이지에서 계약 및 세금 > 계약 섹션으로 이동하여 계약 양식을 작성합니다.
- 세무 조사에 통과합니다. 이렇게 하려면 관리자 페이지에서 계약 및 세금 > 세무 조사 섹션으로 이동하여 해당 양식을 작성합니다.
- 프로덕션 환경으로 전환합니다. 이렇게 하려면 토큰 생성을 위한 요청에서
“sandbox”: true
를 제거하십시오.
오자 또는 기타 텍스트 오류를 찾으셨나요? 텍스트를 선택하고 컨트롤+엔터를 누르세요.