注意必讀
做了很多電商的項(xiàng)目了瞧剖,都在用各大第三方支付剩檀,蘋果已經(jīng)在強(qiáng)制推行內(nèi)購了吠式,簡(jiǎn)單說明一下,如果你購買的商品嘶摊,是在本app中使用和消耗的虛擬貨幣,就一定要用內(nèi)購舟陆,否則會(huì)被拒絕上線矾屯,例如:游戲幣,在線書籍呀袱,app中使用的道具等贸毕。如果購買的就是普通的商品,例如淘寶買東西等夜赵,就不需要用內(nèi)購
現(xiàn)在蘋果有一個(gè) bug 就是你填寫了銀行卡信息之后修改不了只能發(fā)郵件給蘋果等那邊重置,發(fā)郵件給他們處理有多慢你懂得....
一.向appStore提交資料
第一步
第二步
第三步
操作完第三步然后記得保存
第四步
第五步
先點(diǎn)擊Contact Info 的Set Up
第六步
第七步
都填寫完記得保存明棍,然后回到上一個(gè)頁面
第八步
第九步
第十步
第十一步
第十二步
填寫銀行卡信息
第十三步
第十四步
第十五步
第十六步
第十七步
第十八步
第十九步
第二十步
第二十一步
恭喜你現(xiàn)在你完成了添加的信息,下面創(chuàng)建內(nèi)購項(xiàng)目
二.創(chuàng)建內(nèi)購項(xiàng)目
第一步
第二步
根據(jù)自己app的需要選擇類型
第三步
第四步
一直下一步到結(jié)尾
三、添加項(xiàng)目?jī)?nèi)購測(cè)試帳號(hào)
第一步
四寇僧、上代碼
第一步導(dǎo)入StoreKit.framework庫
然后先看.h文件
#import <StoreKit/StoreKit.h>
typedef NS_ENUM(NSInteger, MyJellyShowType)
{
MyJellyShowType_Push = 0,
MyJellyShowType_Present = 1,
};
@interface MyJellyCurrencyViewController : BaseReuqestTableViewController<SKPaymentTransactionObserver,SKProductsRequestDelegate>
{
int buyType;
}
@property (nonatomic) MyJellyShowType showType;
- (void)RequestProductData;
- (void)buy:(int)type;
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
- (void)completeTransaction: (SKPaymentTransaction *)transaction;
- (void)failedTransaction: (SKPaymentTransaction *)transaction;
- (void)restoreTransaction: (SKPaymentTransaction *)transaction;
@end
然后看.m文件
//在內(nèi)購項(xiàng)目中創(chuàng)的商品單號(hào)
#define ProductID_IAP0p600 @"guodong600"http://60
#define ProductID_IAP1p1200 @"guodong1200" //1200
#define ProductID_IAP2p5000 @"guodong5000" //5000
enum{
IAP0p600 = 0,
IAP1p1200,
IAP4p5000,
} buyCoinsT
#pragma mark - 點(diǎn)擊購買按鈕
-(void)buttonClickIndex:(NSInteger)index
{
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
if (index == 0)
{
buyCoinsTag = IAP0p600;
}
else if (index == 1)
{
buyCoinsTag = IAP1p1200;
}else if (index == 2)
{
buyCoinsTag = IAP4p5000;
}
coinNum = [jellyMutAry objectAtIndex:index];
[LoadingTool showLoadingTo:self.view isAfterDelay:NO];
mainTableView.userInteractionEnabled = NO;
[self buy:buyCoinsTag];
}
-(void)buy:(int)type{
buyType = type;
if ([SKPaymentQueue canMakePayments])
{
//允許程序內(nèi)付費(fèi)購買
[self RequestProductData];
}
else
{
//不允許程序內(nèi)付費(fèi)購買
mainTableView.userInteractionEnabled = YES;
[LoadingTool hideProgressHud:self];
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"您的手機(jī)沒有打開程序內(nèi)付費(fèi)購買"
delegate:nil cancelButtonTitle:NSLocalizedString(@"關(guān)閉",nil) otherButtonTitles:nil];
[alerView show];
}
}
#pragma mark - 請(qǐng)求對(duì)應(yīng)的產(chǎn)品信息
-(void)RequestProductData
{
NSArray *product = nil;
switch (buyType)
{
case IAP0p600:
product=[[NSArray alloc] initWithObjects:ProductID_IAP0p600,nil];
break;
case IAP1p1200:
product=[[NSArray alloc] initWithObjects:ProductID_IAP1p1200,nil];
break;
case IAP4p5000:
product=[[NSArray alloc] initWithObjects:ProductID_IAP2p5000,nil];
break;
default:
break;
}
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request=[[SKProductsRequest alloc] initWithProductIdentifiers: nsset];
request.delegate=self;
[request start];
}
#pragma mark - 收到產(chǎn)品反饋信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
SKProduct * selectedProduct = nil;
selectedProduct = [response.products objectAtIndex:0];
SKPayment *payment = [SKPayment paymentWithProduct:selectedProduct];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
#pragma mark - 先商品添加進(jìn)列表 再交易
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions//交易結(jié)果
{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased://交易完成
{
[self completeTransaction:transaction];
}
break;
case SKPaymentTransactionStateFailed://交易失敗
{
//交易失敗
[self failedTransaction:transaction];
[WarningTool showToastHintWithText:@"購買失敗,請(qǐng)重試摊腋!"];
}
break;
case SKPaymentTransactionStateRestored://已經(jīng)購買過該商品
[self restoreTransaction:transaction];
break;
case SKPaymentTransactionStatePurchasing://商品添加進(jìn)列表
break;
default:
break;
}
}
[LoadingTool hideProgressHud:self];
mainTableView.userInteractionEnabled = YES;
}
#pragma mark - 交易完成調(diào)用
- (void) completeTransaction: (SKPaymentTransaction *)transaction{
NSString *product = transaction.payment.productIdentifier;
if ([product length] > 0)
{
NSArray *tt = [product componentsSeparatedByString:@"."];
NSString *bookid = [tt lastObject];
if ([bookid length] > 0)
{
[self recordTransaction:transaction];
}
}
// Remove the transaction from the payment queue.結(jié)束交易
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
#pragma mark - 記錄交易
-(void)recordTransaction:(SKPaymentTransaction *)transaction
{
transactionIdentifier = transaction.transactionIdentifier;
[self verifyPruchase];
// NSString *product = transaction.payment.productIdentifier;
// NSString *applicationUsername = transaction.payment.applicationUsername;
// NSString *transactionIdentifier = transaction.transactionIdentifier;
// // 驗(yàn)證憑據(jù),獲取到蘋果返回的交易憑據(jù)
// // appStoreReceiptURL iOS7.0增加的嘁傀,購買交易完成后兴蒸,會(huì)將憑據(jù)存放在該地址
// NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// // 從沙盒中獲取到購買憑據(jù)
// NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
// NSString *result =[[ NSString alloc] initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding];
// NSString *base64Str = [transaction.transactionReceipt base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
}
- (void)verifyPruchase
{
[LoadingTool showLoadingTo:self.view isAfterDelay:NO];
// 驗(yàn)證憑據(jù),獲取到蘋果返回的交易憑據(jù)
// appStoreReceiptURL iOS7.0增加的细办,購買交易完成后橙凳,會(huì)將憑據(jù)存放在該地址
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 從沙盒中獲取到購買憑據(jù)
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// 發(fā)送網(wǎng)絡(luò)POST請(qǐng)求,對(duì)購買憑據(jù)進(jìn)行驗(yàn)證
NSURL *url = [NSURL URLWithString:XTY_IAP_VerifyReceipt];
// 國(guó)內(nèi)訪問蘋果服務(wù)器比較慢笑撞,timeoutInterval需要長(zhǎng)一點(diǎn)
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
request.HTTPMethod = @"POST";
NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = payloadData;
// 提交驗(yàn)證請(qǐng)求岛啸,并獲得官方的驗(yàn)證JSON結(jié)果
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// 官方驗(yàn)證結(jié)果為空驗(yàn)證失敗
if (result == nil)
{
[LoadingTool hideProgressHud:self];
[WarningTool showToastHintWithText:@"驗(yàn)證失敗"];
return;
}
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
//驗(yàn)證成功
if ([[dict objectForKey:@"status"] integerValue] == 0) {
// 比對(duì)字典中以下信息基本上可以保證數(shù)據(jù)安全
// bundle_id&application_version&product_id&transaction_id
[self addJelly];
}else if ([[dict objectForKey:@"status"] integerValue] == 21007){
// 驗(yàn)證憑據(jù),獲取到蘋果返回的交易憑據(jù)
// appStoreReceiptURL iOS7.0增加的茴肥,購買交易完成后坚踩,會(huì)將憑據(jù)存放在該地址
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 從沙盒中獲取到購買憑據(jù)
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// 發(fā)送網(wǎng)絡(luò)POST請(qǐng)求,對(duì)購買憑據(jù)進(jìn)行驗(yàn)證
NSURL *url = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
// 國(guó)內(nèi)訪問蘋果服務(wù)器比較慢瓤狐,timeoutInterval需要長(zhǎng)一點(diǎn)
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
request.HTTPMethod = @"POST";
NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSString *payload = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = payloadData;
// 提交驗(yàn)證請(qǐng)求瞬铸,并獲得官方的驗(yàn)證JSON結(jié)果
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// 官方驗(yàn)證結(jié)果為空驗(yàn)證失敗
if (result == nil)
{
[LoadingTool hideProgressHud:self];
[WarningTool showToastHintWithText:@"驗(yàn)證失敗"];
return;
}
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:result options:NSJSONReadingAllowFragments error:nil];
if ([[dict objectForKey:@"status"] integerValue] == 0) {
[self addJelly];
}else{
[LoadingTool hideProgressHud:self];
[WarningTool showToastHintWithText:@"驗(yàn)證失敗"];
}
}
else{
[LoadingTool hideProgressHud:self];
[WarningTool showToastHintWithText:@"驗(yàn)證失敗"];
}
}
//失敗
- (void) failedTransaction: (SKPaymentTransaction *)transaction{
if (transaction.error.code != SKErrorPaymentCancelled){}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
//交易恢復(fù)處理
- (void) restoreTransaction: (SKPaymentTransaction *)transaction{
// [self PurchasedTransaction:transaction];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
// [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
}
-(void) paymentQueue:(SKPaymentQueue *) paymentQueue restoreCompletedTransactionsFailedWithError:(NSError *)error{
}
-(void) PurchasedTransaction: (SKPaymentTransaction *)transaction{
NSArray *transactions =[[NSArray alloc] initWithObjects:transaction, nil];
[ self paymentQueue:[SKPaymentQueue defaultQueue] updatedTransactions:transactions];
}
-(void)dealloc{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
//解除監(jiān)聽
}
- (void)addJelly
{
NSMutableDictionary *mutDic = [[NSMutableDictionary alloc]init];
[mutDic setObject:transactionIdentifier forKey:@"flowNO"];
[mutDic setObject:coinNum forKey:@"coinNum"];
[[NetworkRequests sharedClient]requestWithName:XTY_CoinCharge withParameters:mutDic successCallBack:^(MyJellyModel *myJellyModel) {
[LoadingTool hideProgressHud:self];
if ([myJellyModel.status integerValue] == 1)
{
[self beginRefreshing];
}
else
{
[WarningTool showToastHintWithText:myJellyModel.error];
}
} failCallback:^(NSString *error) {
[LoadingTool hideProgressHud:self];
[WarningTool showToastNetError];
}];
}