公司项目要做会员功能,支付方式我采用的是内购In-App Purchases。说实话,我真的不想用苹果的内购功能,不说苹果要收百分之三十的手续费,就说它那么多的坑,我是真的不想往里面跳啊,但公司担心用支付宝、微信支付等方式苹果不让上架,做个开关的话又怕突然下架、甚至封掉开发者帐号。所以,这个坑我就只有跳了, 俗话说:我不入地狱,谁入地狱???!!!
话不多说,开始!
itunes connect里面的就不说了,我只说程序里面的代码部分。
- 首先要导入StoreKit.framework。引用 #import
{
BOOL startBuyAppleProduct;
}
- 添加监听,这个最好写在- (void)viewDidLoad { }中。
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
- 当点某一个按钮的时候先去检测用户是否打开手机内购功能,如果打开了就执行requestProductData:方法请求商品数据,否则提示用户。ProductID是在itunes connect中设置的产品ID。
- (void)performPayFunctionOnIos
{
if([SKPaymentQueue canMakePayments]){
[self requestProductData:ProductID];
}else{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"您的手机没有打开内购功能" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
}
添加产品ID,设置代理并发起请求。请求是从的苹果的服务器请求产品的数据.
- (void)requestProductData:(NSString*)productString{ startBuyAppleProduct = YES; //这里把它设为YES,表明是你发起的请求。 NSArray*product = [[NSArray alloc] initWithObjects:productString,nil]; NSSet*nsset = [NSSet setWithArray:product]; SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset]; request.delegate=self; [request start]; }
- 添加代理方法
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray*product = response.products;
if([product count] ==0){
NSLog(@"没有商品");
return;
}
SKProduct *p = nil;
for (SKProduct *pro in product) {
if ([pro.productIdentifier isEqualToString:ProductID]) {
p = pro;
}
}
SKPayment *payment = [SKPayment paymentWithProduct:p];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
- (void)request:(SKRequest*)request didFailWithError:(NSError*)error {
NSLog(@"商品信息请求错误:%@", error);
}
- (void)requestDidFinish:(SKRequest*)request {
NSLog(@"请求结束");
}
添加监听方法
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction { for(SKPaymentTransaction *tran in transaction){ switch(tran.transactionState) { case SKPaymentTransactionStatePurchased: // 这里要用最开始就定义的BOOL值startBuyAppleProduct来判断下是否是你本次发起的内购, 不是就跳过验证。 不知道为什么每次进这个控制器,它就会走这个监听方法,不在其它的case里判断是因为其它的并没有做什么逻辑处理。 if (startBuyAppleProduct) { [self verifyFinishedTransaction:tran]; } [self restoreTransaction:tran]; NSLog(@"交易完成"); break; case SKPaymentTransactionStatePurchasing: NSLog(@"商品添加进列表"); break; case SKPaymentTransactionStateRestored: NSLog(@"已经购买过商品"); [self restoreTransaction:tran]; break; case SKPaymentTransactionStateFailed: NSLog(@"交易失败"); [self restoreTransaction:tran]; break; default: NSLog(@"other"); [self restoreTransaction:tran]; break; } } }
- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
// 取消订单,或者说是恢复订单
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
// 每次都要把startBuyAppleProduct设置为NO,不然购买成功就不会验证
startBuyAppleProduct = NO;
}
// 验证
- (void)verifyFinishedTransaction:(SKPaymentTransaction *)transaction {
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
NSString * productIdentifier = transaction.payment.productIdentifier;
NSLog(@"%@",transaction.transactionIdentifier);
NSString *receipt = [[NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL] ] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
if ([productIdentifier length] > 0) {
// 向自己的服务器验证购买凭证,用post的方式把receipt传给服务器就可以了。
}
}
}
因为苹果审核的时候是用的测试服务器, 但我们又不知道它的审核什么时间通过,所以最好先验证苹果的测试服务器,如果返回的是21007,再向正式的服务器发起验证。
测试服务器验证链接
https://sandbox.itunes.apple.com/verifyReceipt
正式服务器验证链接
https://buy.itunes.apple.com/verifyReceipt
验证返回的数据其中status为0,也就是”status”:0时就是验证成功了。这个要记住!记住!记住!并不是非零即真!这里零才是真!!!
7. 最后就是移除监听。
-(void)dealloc{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
看嘛,这就弄完了, 应该没有什么问题,我们就假如没有问题。������
希望能给各位一点帮助。