iOS開發(fā) 內(nèi)購流程

注意必讀
做了很多電商的項(xiàng)目了瞧剖,都在用各大第三方支付剩檀,蘋果已經(jīng)在強(qiáng)制推行內(nèi)購了吠式,簡(jiǎn)單說明一下,如果你購買的商品嘶摊,是在本app中使用和消耗的虛擬貨幣,就一定要用內(nèi)購舟陆,否則會(huì)被拒絕上線矾屯,例如:游戲幣,在線書籍呀袱,app中使用的道具等贸毕。如果購買的就是普通的商品,例如淘寶買東西等夜赵,就不需要用內(nèi)購
現(xiàn)在蘋果有一個(gè) bug 就是你填寫了銀行卡信息之后修改不了只能發(fā)郵件給蘋果等那邊重置,發(fā)郵件給他們處理有多慢你懂得....

一.向appStore提交資料
第一步


1749914-225b1c250f5c5382.png

第二步


1749914-f446608344ff5775.png

第三步
1749914-36a3a9752f7f5f09.png

操作完第三步然后記得保存
1749914-880a5bfbd6dbcfd9.png

第四步


1749914-6f05cc110112bc39.png

第五步
先點(diǎn)擊Contact Info 的Set Up
1749914-f154d3324adb13b8.png

第六步
1749914-2602d087074b8edc.png

第七步
都填寫完記得保存明棍,然后回到上一個(gè)頁面
1749914-016ab4e0306b73ff.png

第八步
1749914-6187ffdd8a9be141.png

第九步


1749914-3b216495c5385c19.png

第十步
1749914-f4cd66f1a9ed0174.png

第十一步
1749914-3ade39e8d4e7829e.png

第十二步
填寫銀行卡信息

第十三步


1749914-3773f5c84faae624.png

第十四步


1749914-1defa02638af70b7.png

第十五步
1749914-e8dc793dacabe69c.png

第十六步


1749914-0f12a7caa8d83cae.png

第十七步
1749914-8bdcf11af6a38bd7.png

第十八步
1749914-523d414a44dc9293.png

第十九步
1749914-8345169d6d89b17a.png

第二十步
1749914-5a77feb067f7db7f.png

第二十一步


1749914-bc89f24567bc0b01.png

恭喜你現(xiàn)在你完成了添加的信息,下面創(chuàng)建內(nèi)購項(xiàng)目
二.創(chuàng)建內(nèi)購項(xiàng)目


1749914-7c4f22c9a13ac343.png

第一步


1749914-99a1f3573a5c1d9a.png

第二步
根據(jù)自己app的需要選擇類型

第三步


1749914-e7b6de6a4931ea3c.png

第四步

一直下一步到結(jié)尾

三、添加項(xiàng)目?jī)?nèi)購測(cè)試帳號(hào)


1749914-84662a6fd31a7e7c.png

第一步


1749914-bdb0ef4137eb404f.png

四寇僧、上代碼
第一步導(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];
    }];
}



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市芬首,隨后出現(xiàn)的幾起案子赴捞,更是在濱河造成了極大的恐慌,老刑警劉巖郁稍,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赦政,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)恢着,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門桐愉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掰派,你說我怎么就攤上這事从诲∶蚁郏” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵描扯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我趟薄,道長(zhǎng)绽诚,這世上最難降的妖魔是什么杭煎? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮羡铲,結(jié)果婚禮上蜂桶,老公的妹妹穿的比我還像新娘。我一直安慰自己屎飘,他們只是感情好贾费,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著押桃,像睡著了一般导犹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上磕昼,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天节猿,我揣著相機(jī)與錄音漫雕,去河邊找鬼峰鄙。 笑死吟榴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的兜看。 我是一名探鬼主播仿野,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼她君,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼缔刹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起校镐,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤鸟廓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后引谜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體员咽,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年契讲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捡偏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峡迷。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖枣申,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挟伙,我是刑警寧澤模孩,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布榨咐,位于F島的核電站,受9級(jí)特大地震影響块茁,放射性物質(zhì)發(fā)生泄漏数焊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一遂蛀、第九天 我趴在偏房一處隱蔽的房頂上張望干厚。 院中可真熱鬧,春花似錦所坯、人聲如沸裕坊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饵蒂。三九已至退盯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慰照,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工稚铣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留墅垮,地道東北人算色。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像峡钓,于是被迫代替她去往敵國(guó)和親斥废。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 做了很多電商的項(xiàng)目了淆九,都在用各大第三方支付,作為一名iOS開發(fā)炭庙,蘋果已經(jīng)在強(qiáng)制推行內(nèi)購了焕蹄,所以,你不得不了解一下啦...
    Xcode_6閱讀 1,196評(píng)論 0 0
  • 做了很多電商的項(xiàng)目了,都在用各大第三方支付钾麸,作為一名iOS開發(fā),蘋果已經(jīng)在強(qiáng)制推行內(nèi)購了饭尝,所以,你不得不了解一下啦...
    睡不著的葉閱讀 51,969評(píng)論 93 259
  • 為一名iOS開發(fā),蘋果已經(jīng)在強(qiáng)制推行內(nèi)購了帖池,所以,你不得不了解一下啦肴甸∏舭停可能還有些人不知道哪種情況下一定要用到內(nèi)購,...
    獨(dú)酌丿紅顏閱讀 3,697評(píng)論 2 7
  • 早上起來庶柿,9.30叫男朋友起床秽浇,熱水燒好了,10.00他要上班审残,我在床上躺著卻莫名奇妙的哭了起來斑举。原本自考的日子,...
    7dcc6255d03a閱讀 253評(píng)論 0 1
  • 日子總是很忙碌璧坟,不知不覺又一天雀鹃。晚上涼風(fēng)習(xí)習(xí)铲敛,站在窗前做肩頸和煥然一新,想起邵老師的話伐蒋,希望這個(gè)夏天舒服些迁酸。至于秋...
    misang閱讀 165評(píng)論 0 3