iOS Setup
Setting up in-app purchases for iOS requires configuration in both Xcode and App Store Connect.
App Store Connect Configuration
1. Create Your App Record
- Sign in to App Store Connect
- Navigate to "My Apps"
- Create a new app or select your existing app
- Fill in the required app information
2. Create In-App Purchase Products
- In your app's page, go to Features > In-App Purchases
- Click the + button to create a new product
- Choose your product type:
- Consumable: Can be purchased multiple times (coins, lives, etc.)
- Non-Consumable: One-time purchase (premium features)
- Auto-Renewable Subscription: Recurring subscription
- Non-Renewable Subscription: Time-limited subscription
3. Configure Product Details
For each product, provide:
- Product ID: Unique identifier (e.g.,
com.yourapp.premium
) - Reference Name: Internal name for your team
- Pricing: Select price tier or custom pricing
- Display Name: Name shown to users
- Description: Product description for users
4. Submit for Review
- Add product screenshot (1024x1024px)
- Submit for review (first-time products need approval)
Xcode Configuration
1. Enable In-App Purchase Capability
- Open your project in Xcode
- Select your app target
- Go to Signing & Capabilities
- Click + Capability
- Add In-App Purchase
2. Configure Bundle Identifier
Ensure your bundle identifier in Xcode matches the one in App Store Connect:
- Select your target
- Go to General tab
- Verify Bundle Identifier matches App Store Connect
3. Code Signing
Make sure you have proper code signing set up:
- Go to Signing & Capabilities
- Select your development team
- Choose appropriate provisioning profile
Testing Setup
1. Create Sandbox Test User
- In App Store Connect, go to Users and Access
- Click Sandbox Testers
- Create a new sandbox test user with a unique email
- Important: Use a different email than your developer account
2. Configure Test Environment
On your iOS device:
- Sign out of the App Store
- Go to Settings > App Store
- Sign out of your Apple ID
- Install your app via Xcode or TestFlight
- When prompted for App Store credentials, use your sandbox test user
Code Integration
Basic Setup
import {useIAP, ErrorCode} from 'expo-iap';
const productIds = [
'com.yourapp.premium',
'com.yourapp.coins_100',
'com.yourapp.subscription_monthly',
];
function App() {
const {connected, products, getProducts, requestPurchase, validateReceipt} =
useIAP({
onPurchaseSuccess: (purchase) => {
console.log('Purchase successful:', purchase);
// Handle successful purchase
validatePurchase(purchase);
},
onPurchaseError: (error) => {
console.error('Purchase failed:', error);
// Handle purchase error
},
});
React.useEffect(() => {
if (connected) {
getProducts(productIds);
}
}, [connected]);
const validatePurchase = async (purchase) => {
try {
const result = await validateReceipt(purchase.transactionId);
if (result.isValid) {
// Grant user the purchased content
console.log('Receipt is valid');
}
} catch (error) {
console.error('Validation failed:', error);
}
};
return (
<View>
{products.map((product) => (
<TouchableOpacity
key={product.id}
onPress={() => requestPurchase({request: {sku: product.id}})}
>
<Text>
{product.title} - {product.displayPrice}
</Text>
</TouchableOpacity>
))}
</View>
);
}
💡 Cross-Platform Note: This example shows iOS-specific usage with
sku
. For cross-platform compatibility, include bothsku
andskus
in your request object. See the Core Methods documentation for details.
iOS-Specific Features
Receipt Validation
const validateReceipt = async (productId: string) => {
try {
const result = await validateReceipt(productId);
console.log('Receipt validation result:', {
isValid: result.isValid,
receiptData: result.receiptData,
jwsRepresentation: result.jwsRepresentation, // iOS 15+
});
return result.isValid;
} catch (error) {
console.error('Receipt validation failed:', error);
return false;
}
};
Handling StoreKit Errors
const handlePurchaseError = (error: any) => {
switch (error.code) {
case ErrorCode.E_USER_CANCELLED:
// User cancelled - don't show error
break;
case ErrorCode.E_PAYMENT_NOT_ALLOWED:
Alert.alert('Purchases are not allowed on this device');
break;
case ErrorCode.E_PAYMENT_INVALID:
Alert.alert('Invalid payment information');
break;
default:
Alert.alert('Purchase failed', error.message);
}
};
Common Issues
Product IDs Not Found
Problem: Products return empty or undefined Solution:
- Verify product IDs match exactly between code and App Store Connect
- Ensure products are in "Ready to Submit" or "Approved" state
- Check bundle identifier matches
Sandbox Testing Issues
Problem: "Cannot connect to iTunes Store" error Solution:
- Use a dedicated sandbox test user
- Sign out of regular App Store account
- Verify internet connection
- Try on a real device (simulator may have issues)
Receipt Validation Failures
Problem: Receipt validation returns invalid Solution:
- Check if app is properly signed
- Verify receipt data is not corrupted
- Ensure proper error handling for network issues
Best Practices
- Always validate receipts server-side for production apps
- Handle all error cases gracefully
- Test thoroughly with sandbox users
- Cache purchase state to handle app restarts
- Provide restore functionality for non-consumable products