首先絮叨下為什么寫這篇文章,每個(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)買 成功了