I tried to summarize the implementation of billing that I find difficult. It's very easy to copy and implement. I would be happy if you could use it while customizing it as needed.
class StoreManager: NSObject, SKPaymentTransactionObserver {
static var sharedStore = StoreManager()
var products: [SKProduct] = []
//Define a list of product ids
let productsIdentifiers: Set<String> = []
//Call AppDelegate or before billing to get a list of products
static func setup() {
sharedStore.validateProductsIdentifiersWithRequest()
}
//Get product information from Store
private func validateProductsIdentifiersWithRequest() {
let request = SKProductsRequest(productIdentifiers: productsIdentifiers)
request.delegate = self
request.start()
}
...
}
--Define the Product ID
of the billing item created in App Store Connect.
//Define a list of productId
//Product ID is sample.For id
let productsIdentifiers: Set<String> = ["sample.id"]
-Get a list of Product information based on the defined productsIdentifiers
.
//Get product information from Store
private func validateProductsIdentifiersWithRequest() {
//Request for acquisition
let request = SKProductsRequest(productIdentifiers: productsIdentifiers)
request.delegate = self
request.start()
}
//The result of the acquisition process is`SKProductsRequestDelegate`Will be notified to
extension StoreManager: SKProductsRequestDelegate {
//Product information acquisition completed
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
products = response.products
}
}
//Purchase
func purchaseProduct(_ productIdentifier: String) {
//Check if there is product information corresponding to productIdentifier
guard let product = productForIdentifiers(productIdentifier) else { return }
//Purchase request
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}
//Check if the corresponding product information exists in products
private func productForIdentifiers(_ productIdentifier: String) -> SKProduct? {
return products.filter({ (product: SKProduct) -> Bool in
return product.productIdentifier == productIdentifier
}).first
}
//Called every time transactions change
//Describe the content you want to process according to the state of Transaction
//Note that when you end a transaction, the consumable receipt disappears and the Transaction cannot be restored.
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchasing:
//Added to queue
case .purchased:
//Purchase completed
case .restored:
//Restoration from purchase history completed
case .deferred:
//Purchase processing is pending and approved town
case .failed:
//Request failed before being queued
default:
break
}
}
}
A receipt will be generated on Apple's server once the billing is complete. When verifying receipts, be aware that if you close Transaction, consumable receipts will be deleted and you will not be able to earn income. Subscription receipts, etc. can be obtained all the time even when Transaction is closed, so be careful not to create multiple receipts when verifying receipts and creating data.
When you try to make a purchase with an account that has "Ask to Buy" enabled, your purchase will be suspended and you will be notified by the administrator asking for permission. The Transaction state will be .deferred
until the notification is granted.
This is due to the Family Sharing (https://www.apple.com/jp/family-sharing/) feature.
[IOS] The location of the Sand Box account has changed in iOS 14
Recommended Posts