iOS,蘋果虛擬商品內(nèi)付詳解驻龟,從零到完成支付温眉,2019-04-09

首先絮叨下為什么寫這篇文章,每個(gè)人做每件事都有第一次翁狐,第一次做一件事總有一些彎路要走类溢,我開始搞內(nèi)付的時(shí)候 也是在網(wǎng)上翻了許多文章,但是沒有找到一篇完整的露懒, 蘋果虛擬商品內(nèi)付前期準(zhǔn)備工作又是有許多牽連的闯冷,所以想要寫這篇文章總結(jié)下 ?好了 下面開始講如何實(shí)現(xiàn)內(nèi)購(gòu),


因?yàn)閷?shí)現(xiàn)的過程中有些截圖沒有保存懈词,所以會(huì)有些圖缺失蛇耀,文章重在講解流程和遇到的問題以及各個(gè)流程的關(guān)系

http://www.cnblogs.com/huanghaipo/p/7064383.html參考


文章結(jié)構(gòu):

1:銀行稅務(wù),協(xié)議

2:證書

3:添加內(nèi)購(gòu)虛擬商品信息

4:xcode 配置

5:實(shí)現(xiàn)代碼

6:內(nèi)購(gòu)實(shí)現(xiàn)過程中遇到的問題講解

7:添加測(cè)試賬號(hào)


1:協(xié)議坎弯,稅務(wù)和銀行業(yè)務(wù)

如果你的蘋果賬號(hào)是一個(gè)新的賬號(hào)沒有添加協(xié)議稅務(wù)和銀行業(yè)務(wù)信息蒂窒,那么首先需要添加這些信息,上面參考鏈接里面有荞怒,

如果協(xié)議洒琢,稅務(wù)和銀行業(yè)務(wù)信息沒有添加 那么后面就算實(shí)現(xiàn)了代碼,app會(huì)返回給你的信息是搜索不到商品褐桌,

協(xié)議衰抑,稅務(wù)和銀行業(yè)務(wù)填寫的信息是需要審核的,所以這個(gè)有必要先完成荧嵌,

下圖是我下午填寫的信息第二天看到的狀態(tài)都是有效呛踊,這樣就可以搜索到商品信息了砾淌,



2:證書


一般我們用到的上傳App Store和調(diào)試證書 applepay 是沒有亮點(diǎn)的,但是內(nèi)購(gòu)支付證書需要這個(gè)谭网,

當(dāng)然 你可以在創(chuàng)建appid的時(shí)候 選擇applepay 也可以在創(chuàng)建之后 點(diǎn)擊下面的edit 更改



點(diǎn)擊edit進(jìn)入下圖

如上圖選擇applepay 點(diǎn)擊edit


上圖如果點(diǎn)擊進(jìn)來沒有merchant ID 那么需要在1出創(chuàng)建

參考?https://blog.csdn.net/shenguanhua/article/details/50772186

完成之后 會(huì)有一個(gè)這樣的證書


安裝到項(xiàng)目里面是這樣的


證書只是講解了與普通測(cè)試上架證書的不同汪厨,沒有很詳細(xì)的步驟講解,

3:添加內(nèi)購(gòu)虛擬商品

這個(gè)問題 網(wǎng)上文章最多愉择,參考?https://www.cnblogs.com/fengmin/p/8126079.html


如上圖所示劫乱,是添加完商品之后的樣子,



上面圖箭頭指向的審核信息一定也要填寫锥涕,


上圖 箭頭指向的產(chǎn)品ID衷戈,是在程序里面搜索此商品的標(biāo)識(shí),只要是唯一就可以层坠,程序里面就是通過這個(gè)id搜索到這個(gè)商品的殖妇,



如上圖 我的審核信息沒有填寫,點(diǎn)擊保存破花,會(huì)出現(xiàn)元數(shù)據(jù)丟失


4:xcode配置



如果 打開Apple Pay谦趣,如果是新的xocde 沒有添加賬號(hào) 1 和2 的箭頭指向 會(huì)有錯(cuò)誤,此時(shí) 點(diǎn)擊 3箭頭指向的加號(hào)或者刷新會(huì)有錯(cuò)誤提示 座每,需要xcode添加賬號(hào)



如上圖 點(diǎn)擊xocde->preferences?



點(diǎn)擊 箭頭指向加號(hào)添加賬號(hào) 前鹅,完成之后 點(diǎn)擊 3處的刷新 就好了

1處的?merchant ID是簽名創(chuàng)建了才會(huì)有,這里如果沒有?merchant ID 那么證書是有問題的 尺栖,簽名見了如何創(chuàng)建merchant ID


4 :代碼

上面一些配置信息比較復(fù)雜嫡纠,下面就是簡(jiǎn)單的代碼了烦租,代碼我整個(gè)粘貼的.m里面的所有代碼 如果網(wǎng)站編碼沒有問題 復(fù)制粘貼就可以運(yùn)行延赌,

#import "ViewController.h"

#import

@interface ViewController ()<SKPaymentTransactionObserver,SKProductsRequestDelegate>

@property (nonatomic,copy) NSString *currentProId;

@end

@implementation ViewController

- (void)viewDidLoad {

? ? [super viewDidLoad];


? ? UIButton *button2 = [UIButton buttonWithType:UIButtonTypeCustom];

? ? button2.frame=CGRectMake(300,100,100,100);

? ? button2.backgroundColor = [UIColor greenColor];

? ? [button2setTitle:@"6元" forState:UIControlStateNormal];

? ? [button2addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchDown];

? ? [self.viewaddSubview:button2];


}

- (void)btnClick:(UIButton*)button

{

? ? [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

? ? _currentProId = @"201904081503";//產(chǎn)品id

? ? if([SKPaymentQueue canMakePayments]){

? ? ? ? [self requestProductData:_currentProId];

? ? }else{

? ? ? ? NSLog(@"不允許程序內(nèi)付費(fèi)");

? ? }

}

//去蘋果服務(wù)器請(qǐng)求商品

- (void)requestProductData:(NSString*)type{

? ? NSLog(@"-------------請(qǐng)求對(duì)應(yīng)的產(chǎn)品信息----------------");


//? ? [SVProgressHUD showWithStatus:nil maskType:SVProgressHUDMaskTypeBlack];





? ? NSArray*product = [[NSArrayalloc]initWithObjects:type,nil];


? ? NSSet*nsset = [NSSetsetWithArray:product];

? ? SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];

? ? request.delegate=self;

? ? [requeststart];


}

//收到產(chǎn)品返回信息

- (void)productsRequest:(SKProductsRequest*)request didReceiveResponse:(SKProductsResponse*)response{


? ? NSLog(@"--------------收到產(chǎn)品反饋消息---------------------");

? ? NSArray*product = response.products;

? ? if([productcount] ==0){

//? ? ? ? [SVProgressHUD dismiss];

? ? ? ? NSLog(@"--------------沒有商品------------------");

? ? ? ? return;

? ? }


? ? NSLog(@"productID:%@", response.invalidProductIdentifiers);

? ? NSLog(@"產(chǎn)品付費(fèi)數(shù)量:%lu",(unsignedlong)[product count]);


? ? SKProduct*p =nil;

? ? for(SKProduct*proinproduct) {

? ? ? ? NSLog(@"%@", [prodescription]);

? ? ? ? NSLog(@"%@", [pro localizedTitle]);

? ? ? ? NSLog(@"%@", [pro localizedDescription]);

? ? ? ? NSLog(@"%@", [proprice]);

? ? ? ? NSLog(@"%@", [pro productIdentifier]);


? ? ? ? if([pro.productIdentifierisEqualToString:_currentProId]){

? ? ? ? ? ? p = pro;

? ? ? ? }

? ? }


? ? SKPayment*payment = [SKPaymentpaymentWithProduct:p];


? ? NSLog(@"發(fā)送購(gòu)買請(qǐng)求");

? ? [[SKPaymentQueue defaultQueue] addPayment:payment];

}

//請(qǐng)求失敗

- (void)request:(SKRequest*)request didFailWithError:(NSError*)error{

//? ? [SVProgressHUD showErrorWithStatus:@"支付失敗"];

? ? NSLog(@"------------------錯(cuò)誤-----------------:%@", error);

}

- (void)requestDidFinish:(SKRequest*)request{

//? ? [SVProgressHUD dismiss];

? ? NSLog(@"------------反饋信息結(jié)束-----------------");

}

//沙盒測(cè)試環(huán)境驗(yàn)證

#define SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"

//正式環(huán)境驗(yàn)證

#define AppStore @"https://buy.itunes.apple.com/verifyReceipt"

/**

?*? 驗(yàn)證購(gòu)買,避免越獄軟件模擬蘋果請(qǐng)求達(dá)到非法購(gòu)買問題

?*

?*/

-(void)verifyPurchaseWithPaymentTransaction{

? ? //從沙盒中獲取交易憑證并且拼接成請(qǐng)求體數(shù)據(jù)

? ? NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];

? ? NSData*receiptData=[NSDatadataWithContentsOfURL:receiptUrl];


? ? NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//轉(zhuǎn)化為base64字符串


? ? NSString*bodyString = [NSStringstringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接請(qǐng)求數(shù)據(jù)

? ? NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];



? ? //創(chuàng)建請(qǐng)求到蘋果官方進(jìn)行購(gòu)買驗(yàn)證

? ? NSURL*url=[NSURLURLWithString:SANDBOX];

? ? NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url];

? ? requestM.HTTPBody=bodyData;

? ? requestM.HTTPMethod=@"POST";

? ? //創(chuàng)建連接并發(fā)送同步請(qǐng)求

? ? NSError*error=nil;

? ? NSData *responseData=[NSURLConnection sendSynchronousRequest:requestM returningResponse:nil error:&error];

? ? if(error) {

? ? ? ? NSLog(@"驗(yàn)證購(gòu)買過程中發(fā)生錯(cuò)誤叉橱,錯(cuò)誤信息:%@",error.localizedDescription);

? ? ? ? return;

? ? }

? ? NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];

? ? NSLog(@"%@",dic);

? ? if([dic[@"status"]intValue]==0){

? ? ? ? NSLog(@"購(gòu)買成功挫以!");

? ? ? ? NSDictionary*dicReceipt= dic[@"receipt"];

? ? ? ? NSDictionary*dicInApp=[dicReceipt[@"in_app"]firstObject];

? ? ? ? NSString*productIdentifier= dicInApp[@"product_id"];//讀取產(chǎn)品標(biāo)識(shí)

? ? ? ? //如果是消耗品則記錄購(gòu)買數(shù)量,非消耗品則記錄是否購(gòu)買過

? ? ? ? NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];

? ? ? ? if([productIdentifierisEqualToString:@"123"]) {

? ? ? ? ? ? intpurchasedCount=[defaultsintegerForKey:productIdentifier];//已購(gòu)買數(shù)量

? ? ? ? ? ? [[NSUserDefaultsstandardUserDefaults]setInteger:(purchasedCount+1)forKey:productIdentifier];

? ? ? ? }else{

? ? ? ? ? ? [defaultssetBool:YESforKey:productIdentifier];

? ? ? ? }

? ? ? ? //在此處對(duì)購(gòu)買記錄進(jìn)行存儲(chǔ)窃祝,可以存儲(chǔ)到開發(fā)商的服務(wù)器端

? ? }else{

? ? ? ? NSLog(@"購(gòu)買失敗掐松,未通過驗(yàn)證!");

? ? }

}

//監(jiān)聽購(gòu)買結(jié)果

- (void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray*)transaction{

? ? for(SKPaymentTransaction*tranintransaction){

? ? ? ? switch(tran.transactionState) {

? ? ? ? ? ? case SKPaymentTransactionStatePurchased:{

? ? ? ? ? ? ? ? NSLog(@"交易完成");

? ? ? ? ? ? ? ? // 發(fā)送到蘋果服務(wù)器驗(yàn)證憑證

? ? ? ? ? ? ? ? [self verifyPurchaseWithPaymentTransaction];

? ? ? ? ? ? ? ? [[SKPaymentQueue defaultQueue] finishTransaction:tran];


? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case SKPaymentTransactionStatePurchasing:

? ? ? ? ? ? ? ? NSLog(@"商品添加進(jìn)列表");


? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case SKPaymentTransactionStateRestored:{

? ? ? ? ? ? ? ? NSLog(@"已經(jīng)購(gòu)買過商品");


? ? ? ? ? ? ? ? [[SKPaymentQueue defaultQueue] finishTransaction:tran];

? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case SKPaymentTransactionStateFailed:{

? ? ? ? ? ? ? ? NSLog(@"交易失敗");

? ? ? ? ? ? ? ? [[SKPaymentQueue defaultQueue] finishTransaction:tran];

//? ? ? ? ? ? ? ? [SVProgressHUD showErrorWithStatus:@"購(gòu)買失敗"];

? ? ? ? ? ? }

? ? ? ? ? ? ? ? break;

? ? ? ? ? ? default:

? ? ? ? ? ? ? ? break;

? ? ? ? }

? ? }

}

//交易結(jié)束

- (void)completeTransaction:(SKPaymentTransaction*)transaction{

? ? NSLog(@"交易結(jié)束");


? ? [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}

- (void)dealloc{

? ? [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];

}

@end




6: ?實(shí)現(xiàn)過程中遇到的問題粪小,

在查找網(wǎng)上資料的時(shí)候大磺,沒有找到一篇很完整的文章,所以在開發(fā)的過程中探膊,會(huì)出現(xiàn)許多問題杠愧,我在上面講解的過程中也 有提到 ,

1:銀行稅務(wù)逞壁,協(xié)議

2:證書

3:添加內(nèi)購(gòu)虛擬商品信息

4:xcode 配置

5:實(shí)現(xiàn)代碼

上面5個(gè)人步驟 在實(shí)現(xiàn)內(nèi)購(gòu)的過程中都是必要的流济,我在網(wǎng)站找資料的時(shí)候 沒有遇到一個(gè)很完整的文章所以遇到了一些問題锐锣,如果上面5個(gè)步驟都完成了,應(yīng)該不會(huì)有什么問題



7:添加測(cè)試賬號(hào)


在用戶和訪問里面 沙箱技術(shù)绳瘟,測(cè)試員添加測(cè)試賬號(hào) 雕憔,我的賬號(hào)是我自己的appleid ,添加測(cè)試員不能添加當(dāng)前賬戶的郵箱id糖声,斤彼,我在購(gòu)買的過程中,沒有使用沙箱技術(shù)里面測(cè)試員的賬戶購(gòu)買了 結(jié)果購(gòu)買失敗姨丈,于是用朋友的appleid 添加了 測(cè)試員 畅卓,再次用測(cè)試員的賬戶購(gòu)買 成功了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蟋恬,隨后出現(xiàn)的幾起案子翁潘,更是在濱河造成了極大的恐慌,老刑警劉巖歼争,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拜马,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡沐绒,警方通過查閱死者的電腦和手機(jī)俩莽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乔遮,“玉大人扮超,你說我怎么就攤上這事√0梗” “怎么了出刷?”我有些...
    開封第一講書人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)坯辩。 經(jīng)常有香客問我馁龟,道長(zhǎng),這世上最難降的妖魔是什么漆魔? 我笑而不...
    開封第一講書人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任坷檩,我火速辦了婚禮,結(jié)果婚禮上改抡,老公的妹妹穿的比我還像新娘矢炼。我一直安慰自己,他們只是感情好阿纤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開白布句灌。 她就那樣靜靜地躺著,像睡著了一般阵赠。 火紅的嫁衣襯著肌膚如雪涯塔。 梳的紋絲不亂的頭發(fā)上肌稻,一...
    開封第一講書人閱讀 51,155評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音匕荸,去河邊找鬼爹谭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛榛搔,可吹牛的內(nèi)容都是我干的诺凡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼践惑,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼腹泌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起尔觉,我...
    開封第一講書人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凉袱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后侦铜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體专甩,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年钉稍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涤躲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贡未,死狀恐怖种樱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俊卤,我是刑警寧澤嫩挤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站瘾蛋,受9級(jí)特大地震影響俐镐,放射性物質(zhì)發(fā)生泄漏矫限。R本人自食惡果不足惜哺哼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叼风。 院中可真熱鬧取董,春花似錦、人聲如沸无宿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)孽鸡。三九已至蹂午,卻和暖如春栏豺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背豆胸。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工奥洼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晚胡。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓灵奖,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親估盘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瓷患,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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

  • 愛我者 我愛之
    小帥帥噠閱讀 132評(píng)論 0 0
  • 心里裝著事箫踩,想表達(dá)出來沙咏,卻一直沒有機(jī)會(huì)表達(dá)出來,結(jié)果卻出現(xiàn)在夢(mèng)里班套,被夢(mèng)驚醒了肢藐,或許這就是我們常說的“日有所思夜有所...
    我叫小小舒閱讀 507評(píng)論 0 0
  • 時(shí)間讓我學(xué)會(huì)了思考,有時(shí)在想吱韭,什么是真正的幸福吆豹?其實(shí)并不是自己開心就行,而是看到周圍的人開心也是種幸福理盆。真正的夫妻...
    曉兒說夢(mèng)閱讀 285評(píng)論 0 1
  • 在我們的身上多多少少都有父母的影子猿规,一方面來自遺傳因素衷快,父母把他們的優(yōu)良基因組合,給予我們姨俩。另一方面則是來自父母的...
    我是旭日閱讀 297評(píng)論 0 2