iOS Quick Start
To get access to the Xsolla Mobile SDK during Developer Preview phase, please fill out the form ↗ (https://xsolla.com/mobile-sdk).
Getting Started
iOS — Effective Apr 30, 2025: Developers may include external payment links in U.S. apps. The Xsolla SDK aligns with Apple’s updated guidelines.
This quick start guide will walk you through integrating Xsolla Mobile SDK to accept payments in your game. Using a pre-configured test project ID, we'll cover the essentials: setting up basic user authentication, importing SKUs, and processing a test payment. By the end, you'll have a functional payment system integrated into your game, demonstrating how Xsolla can streamline your monetization process. Let's get started and have your game accepting payments in just a few simple steps!
⚡ DMA-ready & revenue-boosting: leverage direct IPA distribution alongside in-app compliance with DMA—unlocking access to 1,000+ global payment methods and bypassing app-store fees to maximize your margins.
Install the SDK
The Xsolla Mobile SDK is distributed as an XCFramework named XsollaMobileSDK.xcframework.
To install it manually in your Xcode project:
- Open your Xcode project.
- Go to the General tab of your target.
- Drag and drop the
XsollaMobileSDK.xcframeworkinto the Frameworks, Libraries, and Embedded Content section. - Ensure Embed & Sign is selected from the dropdown menu next to the framework.

Configure the SDK
Xsolla Mobile SDK must be configured with the project ID and login project ID from the Publisher Account. As a starting point, example IDs can be used:
- Objective-C
- Swift
For compliance in the U.S. regarding redirecting players to the web, set openExternalBrowser to YES:
settings.openExternalBrowser = YES;
For in-app payment compliance in Europe under the DMA, set openExternalBrowser to NO:
settings.openExternalBrowser = NO;
#import <XsollaMobileSDK/StoreKitWrapper.h>
SKPaymentSettings* settings = [[SKPaymentSettings alloc] initWithProjectId: 77640
loginProjectId:@"026201e3-7e40-11ea-a85b-42010aa80004"
platform: SKPaymentPlatformStandalone
paystationUIThemeId: SKPaystationThemeDark
paystationUISize: SKPaystationSizeMedium];
settings.useSandbox = YES;
settings.openExternalBrowser = ... // assign the required value
SKPaymentQueue* queue = [SKPaymentQueue defaultQueue];
[queue startWithSettings: settings];
[queue addTransactionObserver: self];
For compliance in the U.S. regarding redirecting players to the web, set openExternalBrowser to TRUE:
settings.openExternalBrowser = true;
For in-app payment compliance in Europe under the DMA, set openExternalBrowser to FALSE:
settings.openExternalBrowser = false;
import XsollaMobileSDK
let settings = SKPaymentSettings(projectId: 77640,
loginProjectId: "026201e3-7e40-11ea-a85b-42010aa80004",
platform: .standalone)
settings.useSandbox = true;
settings.openExternalBrowser = ... // assign the required value
SKPaymentQueue.default().start(settings)
SKPaymentQueue.default().add(self)
Setup URL scheme for the target:
- Select your project in the project navigator
- Select your target
- Open the Info tab
- Click the ➕ button in the URL types section
- Set the URL Scheme to
$(PRODUCT_BUNDLE_IDENTIFIER)

Detecting iOS Storefront
To determine the current iOS storefront and control SDK functionality based on the region, use the following code snippets:
- Objective-C
- Swift
[SKPaymentQueue loadCurrentStorefrontCountryCodeWithCompletion:^(NSString* _Nullable countryCode) {
settings.enablePayments = countryCode && [countryCode isEqualToString:@"USA"];
[[SKPaymentQueue defaultQueue] startWithSettings:settings];
}];
SKPaymentQueue.loadCurrentStorefrontCountryCode { countryCode in
settings.enablePayments = countryCode == "USA"
SKPaymentQueue.default().start(settings)
}
The loadCurrentStorefrontCountryCode method asynchronously retrieves the three-letter country code for the current Storefront. You can use this information to enable or disable SDK functionality for specific regions.
For more information about iOS Storefront detection, please refer to our detailed guide: How to detect iOS Storefront
Initialize the SDK
Initialization is done using settings created in previous step. Put this logic somewhere in your initialization code, perhaps, in AppDelegate's didFinishLaunchingWithOptions ↗ (https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622921-application).
- Objective-C
- Swift
SKPaymentQueue* queue = [SKPaymentQueue defaultQueue];
[queue startWithSettings: settings]; // settings from the previous step
// conform your class to SKPaymentTransactionObserver and implement its method
@interface YourClass (SKPaymentTransactionObserver) <SKPaymentTransactionObserver>
@end
@implementation YourClass (SKPaymentTransactionObserver)
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for(SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStateFailed:
// purchase failed, present an error
break;
case SKPaymentTransactionStatePurchased:
// award the player with the purchase of the SKU - transaction.payment.productIdentifier
break;
default: break;
}
}
}
@end
SKPaymentQueue.default().start(settings)
SKPaymentQueue.default().add(self)
// conform your class to SKPaymentTransactionObserver and implement its method
extension YourClass: SKPaymentTransactionObserver {
func paymentQueue(_: SKPaymentQueue, updatedTransactions: [SKPaymentTransaction]) {
for transaction in updatedTransactions {
switch transaction.transactionState {
case .failed:
// purchase failed, present an error
case .purchased:
// award the player with the purchase of the SKU - transaction.payment.productIdentifier
default:
break
}
}
}
}
After SKPaymentQueue is started and observer is added, application can request SKU informations:
- Objective-C
- Swift
NSSet *skus = [NSSet setWithArray:@[@"your_sku1", @"your_sku2"]];
SKProductsRequest* req = [[SKProductsRequest alloc] initWithProductIdentifiers:skus];
req.delegate = self;
[req start];
// conform your class to SKProductsRequestDelegate and implement its method
@interface YourClass (SKProductsRequestDelegate) <SKProductsRequestDelegate>
@end
@implementation YourClass (SKProductsRequestDelegate)
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
// save loaded products somewhere
self.products = response.products
}
@end
let skus: Set<String> = ["your_sku1", "your_sku2"]
let req = SKProductsRequest(productIdentifiers: skus)
req.delegate = self
req.start()
// conform your class to SKProductsRequestDelegate and implement its method
extension YourClass: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
// save loaded products somewhere
self.products = response.products
}
}
Make a Purchase
After getting product details in previous step, we can use it to create payment and initiate purchase:
- Objective-C
- Swift
SKProduct *product = ...; // previously fetched product
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
Purchase result will become known in paymentQueue:updatedTransactions: method:
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for(SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStateFailed:
// Always acknowledge transaction and finish it
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStatePurchased:
// here you can save the purchase and award it to the user
// Always acknowledge transaction and finish it after it was saved
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
default: break;
}
}
}
let product = ... // previously fetched product
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
Purchase result will become known in paymentQueue(_:updatedTransactions:) method:
func paymentQueue(_: SKPaymentQueue, updatedTransactions: [SKPaymentTransaction]) {
for transaction in updatedTransactions {
switch transaction.transactionState {
case .failed:
// Always acknowledge transaction and finish it
SKPaymentQueue.default().finishTransaction(transaction)
case .purchased:
// here you can save the purchase and award it to the user
// Always acknowledge transaction and finish it after it was saved
SKPaymentQueue.default().finishTransaction(transaction)
default:
break
}
}
}
Collect payment
The SDK relies on Xsolla Pay Station for secure payment collections.
These steps will take your through a test payment collection flow:
-
Choose the card payment method:

-
Use one of the test cards listed here ↗ (https://developers.xsolla.com/doc/pay-station/testing/test-cards) and click Pay to confirm the payment:

-
Once the payment goes through, you'll see a confirmation:

What's next?
Congratulations! 🎉
You've successfully integrated Xsolla Mobile SDK and processed your first test payment. This achievement unlocks access to over 1000 global payment methods and sets the foundation for integrating more Xsolla solutions, including our powerful Web Shop.
You've mastered the basics:
- ✅ User authentication
- ✅ SKU management
- ✅ Secure payment processing
This is just the beginning of optimizing your game's monetization. Ready to explore more? Check out our documentation for advanced features and other Xsolla products to further boost your game's success!
The next thing you need to do is to create your own Publisher Account and set up a new project using one of the suggested methods.