创建观察者处理对支付队列
class StoreObserver: NSObject, SKPaymentTransactionObserver {
//Initialize the store observer.
override init() {
super.init()
//Other initialization here.
}
//Observe transaction updates.
func paymentQueue(_ queue: SKPaymentQueue,updatedTransactions transactions: [SKPaymentTransaction]) {
//Handle transaction states here.
}
}
AppDelegate处理
import StoreKit
let iapObserver = StoreObserver()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//[[SKPaymentQueue defaultQueue] addTransactionObserver:self<img src="];" alt="" width="50%" />
SKPaymentQueue.default().add(iapObserver)
return true
}
func applicationWillTerminate(_ application: UIApplication) {
SKPaymentQueue.default().remove(iapObserver)
}
遵循SKProductsRequestDelegate,SKPaymentTransactionObserver协议
获取产品信息
//确认授权
var isAuthorizedForPayments: Bool {
return SKPaymentQueue.canMakePayments()
}
//请求 继承<SKProductsRequestDelegate>协议
fileprivate func fetchProducts(matchingIdentifiers identifiers: [String]) {
// Create a set for the product identifiers.
let productIdentifiers = Set(identifiers)
// Initialize the product request with the above identifiers.
productRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productRequest.delegate = self
// Send the request to the App Store.
productRequest.start()
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *pro = response.products;
if (pro.count > 0) {
SKProduct *product;
for (SKProduct *pid in pro) {
NSLog(@"描述信息-> %@",pid.description);
NSLog(@"产品标题-> %@; 产品描述-> %@",pid.localizedTitle,pid.localizedDescription);
NSLog(@"价格-> %@",pid.price);
product = pid;
}
[[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProduct:(SKProduct *)product]];
}else {
NSLog(@"无法获得商品");
}
}
- (void)requestDidFinish:(SKRequest *)request {
NSLog(@"处理交易请求完成");
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(@"处理交易请求失败");
}
发起购买
//通过上一步从apple获取的商品信息发起
SKProduct *product = <# 上面回调方法里pro中要购买的商品 #>;
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
payment.quantity = 1;//商品数量
[[SKPaymentQueue defaultQueue] addPayment:payment]
//自行设置发起(确认商品ID真实有效)
SKMutablePayment *payment = [[SKMutablePayment alloc] init];
payment.applicationUsername = _orderId; //透传参数。可以传你自己的订单号(不稳定)
payment.productIdentifier = _productId; //商品ID payment.quantity = _count; //商品数量,一般默认都传1
[[SKPaymentQueue defaultQueue] addPayment:payment];
购买结果回调
- (void)paymentQueue:(SKPaymentQueue *)queue
updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
//交易完成
[self paymentTransactionPurchased];
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
break;
case SKPaymentTransactionStatePurchasing:
//交易中
[self paymentTransactionPurchasing];
break;
case SKPaymentTransactionStateRestored:
//已经购买过
[self paymentTransactionRestored];
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
break;
case SKPaymentTransactionStateFailed:
//交易失败
[self paymentTransactionFailed:tran];
break;
default:
break;
}
}
}
购买凭证检验
- (void)paymentTransactionPurchased {
NSURL *receiptUrl = NSBundle.mainBundle.appStoreReceiptURL;
NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
if (!receiptData) {
return;
}
NSString *receiptStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSLog(@"订单信息-> %@",receiptStr);
//验证购买
//收据(自行验证Or后台验证)
[self verify_IapCode:receiptStr];
}
- (void)paymentTransactionPurchasing {
NSLog(@"交易中");
}
- (void)paymentTransactionRestored {
NSLog(@"已经过买过");
}
- (void)paymentTransactionFailed:(SKPaymentTransaction *)transaction {
NSError *error = transaction.error;
if (error) {
if (error.code != SKErrorPaymentCancelled) {
NSLog(@"交易失败");
}else {
NSLog(@"交易取消");
}
}else {
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
}
交易结束
在适当位置
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
storeKit
storeKitV1:
- Original API for In-App Purchase: 一个使用 App Store 收据提供交易信息的API,从 iOS 3、macOS 10.7、tvOS 9 和 watchOS 6.2 开始提供。
storeKitV2:
- In-App Purchase: 一个基于 Swift 的 API,以 JSON Web Signature (JWS) 格式提供 Apple 签名交易验证,从 iOS 15、macOS 12、tvOS 15 和 watchOS 8 开始提供
Link Binary with Libraries 直接添加
内购退款
退款通知--orderId--查对应transaction 交易信息
通过用户的任一个 originalTransactionId 可以查到这个用户的所有退款记录订单
当用户申请退款时,苹果通知(CONSUMPTION_REQUEST)开发者服务器,开发者可在12小时内,提供用户的信息(比如游戏金币是否已消费、用户充值过多少钱、退款过多少钱等),最后苹果收到这些信息,协助“退款决策系统” 来决定是否允许用户退款!详细见文档:[Send Consumption Information(developer.apple.com/documentati…)
#防掉单# 防hook
建议通过KeyChain,发起支付时缓存订单号,校验凭证成功后清理 掉单时:
- SKPaymentQueue 检测是否有未完成的交易----通过订单号请求服务器查询支付结果
- KeyChain 未清理单号----通过订单号请求服务器查询支付结果