iOS 应用内支付(内购)

  • 总结一些添加内购可能遇到的问题

一、iTunes Connect 相关设置

  • APP - 功能 - App内购买项目
  • 点 + 添加产品
  • 根据需求选择产品类型,上传截图

二、代码相关

  • 添加第三方库 StoreKit.framework
  • 导入头文件
#import 
#import 
  • 购买
-(id)initWithDelegate:(id)delegate{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    self.delegate = delegate;
    return self;
}

-(void)removePaymentFromQueue{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    self.delegate = nil;
}

-(void)buy:(NSString*)productId{
    if(![SKPaymentQueue canMakePayments]){
        pr(@"error:不支持内购");
    }else{
        NSSet *nsset = [NSSet setWithArray:@[productId]];
        SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
        request.delegate=self;
        [request start];
    }
}

#pragma mark SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    NSArray *productArray = response.products;
    if(productArray != nil && productArray.count>0){
        SKMutablePayment * payment = [SKMutablePayment paymentWithProduct:productArray[0]];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
}
#pragma mark SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
    for(SKPaymentTransaction* transaction in transactions){
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchased://交易完成
                if ([self.delegate respondsToSelector:@selector(didSuccess:)]) {
                    [self.delegate didSuccess:transaction];
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStateRestored://已经购买过
                if ([self.delegate respondsToSelector:@selector(didRestored:)]) {
                    [self.delegate didRestored:transaction];
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed://购买失败
                if ([self.delegate respondsToSelector:@selector(didFiled:)]) {
                    [self.delegate didFiled:transaction];
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            default:break;
        }
    }
}

- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions{
    pr(@"transactions:%@",transactions);
}
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error{
    pr(@"error:%@",error);
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue{
    pr(@"queue:%@",queue);
}
- (void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads{
    pr(@"downloads:%@",downloads);
}
  • 遇到的问题
    • Payment.productIdentifier属性对应产品,不能修改,否则找不到对应产品会返回错误:无法连接 iTunes Connect
    • Payment.applicationUsername属性会在支付完成后置为null,不能使用
    • [self.delegate didSuccess:transaction]的回调中,要将支付凭证传给服务器,由服务器向苹果验证支付结果。支付凭证desc的获取如下:
NSData * receiptData = [NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL]];
NSString * desc = [receiptData base64EncodedStringWithOptions:0];
  • 向苹果服务端验证票据
//向苹果苹果服务器验证支付结果
- (void)dd {
    NSURLRequest * appstoreRequest = [NSURLRequest requestWithURL:[[NSBundle mainBundle]appStoreReceiptURL]];
    NSData * receiptData = [NSURLConnection sendSynchronousRequest:appstoreRequest returningResponse:nil error:nil];

    // Create the JSON object that describes the request
    NSError *error;
    NSDictionary *requestContents = @{
                                      @"receipt-data": [receiptData base64EncodedStringWithOptions:0]
                                      };
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
                                                          options:0
                                                            error:&error];

    if (!requestData) { /* ... Handle error ... */ }

    // Create a POST request with the receipt data.
    NSURL *storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
    NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
    [storeRequest setHTTPMethod:@"POST"];
    [storeRequest setHTTPBody:requestData];

    // Make a connection to the iTunes Store on a background queue.
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                               if (connectionError) {
                                   /* ... Handle error ... */
                               } else {
                                   NSError *error;
                                   NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
                                   if (!jsonResponse) {
                                       /* ... Handle error ...*/
                                   }
                                   /* ... Send a response back to the device ... */
                               }
                           }];

}

你可能感兴趣的:(iOS 应用内支付(内购))