【详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!】【二】
第二步:申请测试账号,利用沙盒测试模拟AppStore购买道具流程! 回到itunesconnect主页中,选择“Manage Users”然后选择“Test User”,然后出现的界面如下图: 这里Himi已经创建了两个测试账号了,点击界面中的 “Add New User”进行创建即可;记住账号和密码哈,记不住就删掉重新建 娃哈哈~(切记:不能用于真正的AppStore中使用此账号,不仅不能用,而且一旦AppStore发现后果你懂得~) 第三步:在项目中申请购买产品代码以及监听; 这里关于购买的代码部分呢,我都有备注的,Himi这里就不详细讲解了,Himi只是在代码后介绍几点值得注意的地方: 这里Himi是新建的一个Cocos2d的项目,然后给出HelloWorldLayer.h以及HelloWorldLayer.m的全部代码,所有购买代码也全在里面也对应有Himi的注释! HelloWorldLayer.h // //HelloWorldLayer.h //buytest // //Createdby华明李on11-10-29. //CopyrightHimi2011年.Allrightsreserved. // //Whenyouimportthisfile,youimportallthecocos2dclasses #import"cocos2d.h" #import<UIKit/UIKit.h> #import<StoreKit/StoreKit.h> enum{ IAP0p99=10, IAP1p99, IAP4p99, IAP9p99, IAP24p99, }buyCoinsTag; @interfaceHelloWorldLayer:CCLayer<SKProductsRequestDelegate,SKPaymentTransactionObserver> { intbuyType; } +(CCScene*)scene; -(void)requestProUpgradeProductData; -(void)RequestProductData; -(bool)CanMakePay; -(void)buy:(int)type; -(void)paymentQueue:(SKPaymentQueue*)queueupdatedTransactions:(NSArray*)transactions; -(void)PurchasedTransaction:(SKPaymentTransaction*)transaction; -(void)completeTransaction:(SKPaymentTransaction*)transaction; -(void)failedTransaction:(SKPaymentTransaction*)transaction; -(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentTransaction*)transaction; -(void)paymentQueue:(SKPaymentQueue*)paymentQueuerestoreCompletedTransactionsFailedWithError:(NSError*)error; -(void)restoreTransaction:(SKPaymentTransaction*)transaction; -(void)provideContent:(NSString*)product; -(void)recordTransaction:(NSString*)product; @end HelloWorldLayer.m // //IapLayer.m // //CreatedbyHimion11-5-25. //Copyright2011年李华明.Allrightsreserved. // #import"HelloWorldLayer.h" #defineProductID_IAP0p99@"com.buytest.one"//$0.99 #defineProductID_IAP1p99@"com.buytest.two"//$1.99 #defineProductID_IAP4p99@"com.buytest.three"//$4.99 #defineProductID_IAP9p99@"com.buytest.four"//$19.99 #defineProductID_IAP24p99@"com.buytest.five"//$24.99 @implementationHelloWorldLayer +(CCScene*)scene { CCScene*scene=[CCScenenode]; HelloWorldLayer*layer=[HelloWorldLayernode]; [sceneaddChild:layer]; returnscene; } -(id)init { if((self=[superinit])){ CGSizesize=[[CCDirectorsharedDirector]winSize]; CCSprite*iap_bg=[CCSpritespriteWithFile:@"Icon.png"]; [iap_bgsetPosition:ccp(size.width/2,size.height/2)]; [selfaddChild:iap_bgz:0]; //--------------------- //----监听购买结果 [[SKPaymentQueuedefaultQueue]addTransactionObserver:self]; //申请购买 /* enum{ IAP0p99=10, IAP1p99, IAP4p99, IAP9p99, IAP24p99, }buyCoinsTag; */ [selfbuy:IAP24p99]; } returnself; } -(void)buy:(int)type { buyType=type; if([SKPaymentQueuecanMakePayments]){ //[[SKPaymentQueuedefaultQueue]restoreCompletedTransactions]; [selfRequestProductData]; CCLOG(@"允许程序内付费购买"); } else { CCLOG(@"不允许程序内付费购买"); UIAlertView*alerView=[[UIAlertViewalloc]initWithTitle:@"Alert" message:@"Youcan‘tpurchaseinappstore(Himi说你没允许应用程序内购买)" delegate:nilcancelButtonTitle:NSLocalizedString(@"Close(关闭)",nil)otherButtonTitles:nil]; [alerViewshow]; [alerViewrelease]; } } -(bool)CanMakePay { return[SKPaymentQueuecanMakePayments]; } -(void)RequestProductData { CCLOG(@"---------请求对应的产品信息------------"); NSArray*product=nil; switch(buyType){ caseIAP0p99: product=[[NSArrayalloc]initWithObjects:ProductID_IAP0p99,nil]; break; caseIAP1p99: product=[[NSArrayalloc]initWithObjects:ProductID_IAP1p99,nil]; break; caseIAP4p99: product=[[NSArrayalloc]initWithObjects:ProductID_IAP4p99,nil]; break; caseIAP9p99: product=[[NSArrayalloc]initWithObjects:ProductID_IAP9p99,nil]; break; caseIAP24p99: product=[[NSArrayalloc]initWithObjects:ProductID_IAP24p99,nil]; break; default: break; } NSSet*nsset=[NSSetsetWithArray:product]; SKProductsRequest*request=[[SKProductsRequestalloc]initWithProductIdentifiers:nsset]; request.delegate=self; [requeststart]; [productrelease]; } //<SKProductsRequestDelegate>请求协议 //收到的产品信息 -(void)productsRequest:(SKProductsRequest*)requestdidReceiveResponse:(SKProductsResponse*)response{ NSLog(@"-----------收到产品反馈信息--------------"); NSArray*myProduct=response.products; NSLog(@"产品ProductID:%@",response.invalidProductIdentifiers); NSLog(@"产品付费数量:%d",[myProductcount]); //populateUI for(SKProduct*productinmyProduct){ NSLog(@"productinfo"); NSLog(@"SKProduct描述信息%@",[productdescription]); NSLog(@"产品标题%@",product.localizedTitle); NSLog(@"产品描述信息:%@",product.localizedDescription); NSLog(@"价格:%@",product.price); NSLog(@"Productid:%@",product.productIdentifier); } SKPayment*payment=nil; switch(buyType){ caseIAP0p99: payment=[SKPaymentpaymentWithProductIdentifier:ProductID_IAP0p99];//支付$0.99 break; caseIAP1p99: payment=[SKPaymentpaymentWithProductIdentifier:ProductID_IAP1p99];//支付$1.99 break; caseIAP4p99: payment=[SKPaymentpaymentWithProductIdentifier:ProductID_IAP4p99];//支付$9.99 break; caseIAP9p99: payment=[SKPaymentpaymentWithProductIdentifier:ProductID_IAP9p99];//支付$19.99 break; caseIAP24p99: payment=[SKPaymentpaymentWithProductIdentifier:ProductID_IAP24p99];//支付$29.99 break; default: break; } CCLOG(@"---------发送购买请求------------"); [[SKPaymentQueuedefaultQueue]addPayment:payment]; [requestautorelease]; } -(void)requestProUpgradeProductData { CCLOG(@"------请求升级数据---------"); NSSet*productIdentifiers=[NSSetsetWithObject:@"com.productid"]; SKProductsRequest*productsRequest=[[SKProductsRequestalloc]initWithProductIdentifiers:productIdentifiers]; productsRequest.delegate=self; [productsRequeststart]; } //弹出错误信息 -(void)request:(SKRequest*)requestdidFailWithError:(NSError*)error{ CCLOG(@"-------弹出错误信息----------"); UIAlertView*alerView=[[UIAlertViewalloc]initWithTitle:NSLocalizedString(@"Alert",NULL)message:[errorlocalizedDescription] delegate:nilcancelButtonTitle:NSLocalizedString(@"Close",nil)otherButtonTitles:nil]; [alerViewshow]; [alerViewrelease]; } -(void)requestDidFinish:(SKRequest*)request { NSLog(@"----------反馈信息结束--------------"); } -(void)PurchasedTransaction:(SKPaymentTransaction*)transaction{ CCLOG(@"-----PurchasedTransaction----"); NSArray*transactions=[[NSArrayalloc]initWithObjects:transaction,nil]; [selfpaymentQueue:[SKPaymentQueuedefaultQueue]updatedTransactions:transactions]; [transactionsrelease]; } //<SKPaymentTransactionObserver>千万不要忘记绑定,代码如下: //----监听购买结果 //[[SKPaymentQueuedefaultQueue]addTransactionObserver:self]; -(void)paymentQueue:(SKPaymentQueue*)queueupdatedTransactions:(NSArray*)transactions//交易结果 { CCLOG(@"-----paymentQueue--------"); for(SKPaymentTransaction*transactionintransactions) { switch(transaction.transactionState) { caseSKPaymentTransactionStatePurchased://交易完成 [selfcompleteTransaction:transaction]; CCLOG(@"-----交易完成--------"); CCLOG(@"不允许程序内付费购买"); UIAlertView*alerView=[[UIAlertViewalloc]initWithTitle:@"Alert" message:@"Himi说你购买成功啦~娃哈哈" delegate:nilcancelButtonTitle:NSLocalizedString(@"Close(关闭)",nil)otherButtonTitles:nil]; [alerViewshow]; [alerViewrelease]; break; caseSKPaymentTransactionStateFailed://交易失败 [selffailedTransaction:transaction]; CCLOG(@"-----交易失败--------"); UIAlertView*alerView2=[[UIAlertViewalloc]initWithTitle:@"Alert" message:@"Himi说你购买失败,请重新尝试购买~" delegate:nilcancelButtonTitle:NSLocalizedString(@"Close(关闭)",nil)otherButtonTitles:nil]; [alerView2show]; [alerView2release]; break; caseSKPaymentTransactionStateRestored://已经购买过该商品 [selfrestoreTransaction:transaction]; CCLOG(@"-----已经购买过该商品--------"); caseSKPaymentTransactionStatePurchasing://商品添加进列表 CCLOG(@"-----商品添加进列表--------"); break; default: break; } } } -(void)completeTransaction:(SKPaymentTransaction*)transaction { CCLOG(@"-----completeTransaction--------"); //Yourapplicationshouldimplementthesetwomethods. NSString*product=transaction.payment.productIdentifier; if([productlength]>0){ NSArray*tt=[productcomponentsSeparatedByString:@"."]; NSString*bookid=[ttlastObject]; if([bookidlength]>0){ [selfrecordTransaction:bookid]; [selfprovideContent:bookid]; } } //Removethetransactionfromthepaymentqueue. [[SKPaymentQueuedefaultQueue]finishTransaction:transaction]; } //记录交易 -(void)recordTransaction:(NSString*)product{ CCLOG(@"-----记录交易--------"); } //处理下载内容 -(void)provideContent:(NSString*)product{ CCLOG(@"-----下载--------"); } -(void)failedTransaction:(SKPaymentTransaction*)transaction{ NSLog(@"失败"); if(transaction.error.code!=SKErrorPaymentCancelled) { } [[SKPaymentQueuedefaultQueue]finishTransaction:transaction]; } -(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentTransaction*)transaction{ } -(void)restoreTransaction:(SKPaymentTransaction*)transaction { NSLog(@"交易恢复处理"); } -(void)paymentQueue:(SKPaymentQueue*)paymentQueuerestoreCompletedTransactionsFailedWithError:(NSError*)error{ CCLOG(@"-------paymentQueue----"); } #pragmamarkconnectiondelegate -(void)connection:(NSURLConnection*)connectiondidReceiveData:(NSData*)data { NSLog(@"%@",[[[NSStringalloc]initWithData:dataencoding:NSUTF8StringEncoding]autorelease]); } -(void)connectionDidFinishLoading:(NSURLConnection*)connection{ } -(void)connection:(NSURLConnection*)connectiondidReceiveResponse:(NSURLResponse*)response{ switch([(NSHTTPURLResponse*)responsestatusCode]){ case200: case206: break; case304: break; case400: break; case404: break; case416: break; case403: break; case401: case500: break; default: break; } } -(void)connection:(NSURLConnection*)connectiondidFailWithError:(NSError*)error{ NSLog(@"test"); } -(void)dealloc { [superdealloc]; } @end 代码注释的相当清楚了,没有什么可解释的,这里说几点值得注意的地方: 1.添加对应对应代码时不要忘记,添加框架 StoreKit.framework,如何添加框架请看我的博文【iOS-Cocos2d游戏开发之十四】音频/音效/视频播放(利用Cocos2D-iPhone-Extensions嵌入Cocos2d进行视频播放!)! 2.越狱机器无法沙盒测试!模拟器的话,Himi用4.3模拟器不可以,因为提示没有开启程序内付费- -(我都没看到模拟器有store的选项,so~);但是使用iOS5的模拟器可以测试沙盒,但是执行的顺序会有些问题,但是还没真机的童鞋可以使用,建议一切以真机实测为准 3. 千万不要忘记在iTunesConnect中创建AppBundle ID一定要跟你的项目中的info.plist中的Bundle ID保证一致!!!! 4. 以上代码中你需要修改的就是我在HelloWorldLayer.m类中的宏定义的Product ID(产品ID),例如Himi刚才新建了一个产品ID是“com.himi.wahaha" 然后我运行项目截图如下以及运行控制台打印的信息如下: 点击Buy之后运行截图以及打印信息: 输入测试账号密码后以及打印信息: 这里Himi最后一张截图是没有购买成功,这里Himi是故意截图出来的,原因就是想告诉童鞋们: 如果你的产品信息能够正常得到,但是始终无法成功的话,不要着急,因为你的产品要进入iTunes Connect,并且Apple准备好沙箱环境需要一些时间。Himi之前遇到过,然后在一天后我没有修改任何一行代码,但产品ID变为有效并能成功购买。=。 =郁闷ing~~ 起始要使产品发布到Apple的网络系统是需要一段时间的! 好了,写了这么多了,咳咳、Himi继续忙了,做iOS的童鞋们我想此篇将成为你必须收藏的一篇哦~嘿嘿! 本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/706419,如需转载请自行联系原作者