網(wǎng)上關(guān)于蘋(píng)果內(nèi)購(gòu)已經(jīng)有無(wú)數(shù)的文章,最近剛好接觸蘋(píng)果內(nèi)購(gòu),簡(jiǎn)單總結(jié)一下整體流程:
① 蘋(píng)果結(jié)算賬戶(hù)信息,公司信息填寫(xiě)(非開(kāi)發(fā)人員任務(wù))
② 創(chuàng)建新的待提交App版本
③ 創(chuàng)建蘋(píng)果內(nèi)購(gòu)商品信息(寶石,金幣)
④ 創(chuàng)建沙盒測(cè)試賬號(hào)
⑤ 支付功能開(kāi)發(fā)
中間在創(chuàng)建商品信息的時(shí)候圖片格式要求是640920海诲,上傳7501136一直不通過(guò),后來(lái)改了圖片尺寸之后640*960才通過(guò)~
核心代碼:
//沙盒測(cè)試環(huán)境驗(yàn)證
static NSString *SANDBOX=@"https://sandbox.itunes.apple.com/verifyReceipt";
//正式環(huán)境驗(yàn)證
static NSString *AppStore=@"https://buy.itunes.apple.com/verifyReceipt";
@interface ViewController () <SKPaymentTransactionObserver,SKProductsRequestDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)applePayAction:(UIButton *)sender {
if([SKPaymentQueue canMakePayments]){
NSArray *product = [[NSArray alloc] initWithObjects:@"talkmate.coin01",nil];
NSSet *nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate = self;
[request start];
}else{
NSLog(@"FlyElephant-不允許進(jìn)行蘋(píng)果內(nèi)購(gòu)");
}
}
#pragma mark - SKProductsRequestDelegate
//接收到產(chǎn)品返回信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSLog(@"productsRequest----didReceiveResponse-------------------");
NSArray *product = response.products;
if([product count] == 0){
return;
}
NSLog(@"productID:%@", response.invalidProductIdentifiers);
NSLog(@"產(chǎn)品付費(fèi)數(shù)量:%lu",(unsigned long)[product count]);
for (SKProduct *pro in product) {
NSLog(@"%@", [pro description]);
NSLog(@"%@", [pro localizedTitle]);
NSLog(@"%@", [pro localizedDescription]);
NSLog(@"%@", [pro price]);
NSLog(@"%@", [pro productIdentifier]);
SKPayment *payment = [SKPayment paymentWithProduct:pro];
NSLog(@"FlyElephant--發(fā)送蘋(píng)果內(nèi)購(gòu)");
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(@"request---didFailWithError");
}
- (void)requestDidFinish:(SKRequest *)request {
NSLog(@"requestDidFinish");
}
#pragma mark - SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
for(SKPaymentTransaction *tran in transactions){
switch (tran.transactionState) {
case SKPaymentTransactionStatePurchased:{
NSLog(@"交易完成");
[self verifyPurchaseWithPaymentTransaction];
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
}
break;
case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加進(jìn)列表");
break;
case SKPaymentTransactionStateRestored:{
NSLog(@"已經(jīng)購(gòu)買(mǎi)過(guò)商品");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
}
break;
case SKPaymentTransactionStateFailed:{
NSLog(@"交易失敗");
[[SKPaymentQueue defaultQueue] finishTransaction:tran];
}
break;
default:
break;
}
}
}
//交易結(jié)束
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
NSLog(@"交易結(jié)束");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
//驗(yàn)證購(gòu)買(mǎi)檩互,避免越獄軟件模擬蘋(píng)果請(qǐng)求達(dá)到非法購(gòu)買(mǎi)問(wèn)題
-(void)verifyPurchaseWithPaymentTransaction{
//從沙盒中獲取交易憑證并且拼接成請(qǐng)求體數(shù)據(jù)
NSURL *receiptUrl=[[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData=[NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString=[receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];//轉(zhuǎn)化為base64字符串
NSString *bodyString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", receiptString];//拼接請(qǐng)求數(shù)據(jù)
NSData *bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
//創(chuàng)建請(qǐng)求到蘋(píng)果官方進(jìn)行購(gòu)買(mǎi)驗(yàn)證
NSURL *url=[NSURL URLWithString: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)買(mǎi)過(guò)程中發(fā)生錯(cuò)誤特幔,錯(cuò)誤信息:%@",error.localizedDescription);
return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@",dic);
if([dic[@"status"] intValue]==0){
NSDictionary *dicReceipt= dic[@"receipt"];
NSDictionary *dicInApp=[dicReceipt[@"in_app"] firstObject];
NSLog(@"購(gòu)買(mǎi)成功:%@---%@",dicReceipt,dicInApp);
//服務(wù)端處理,或者本地處理
}else{
NSLog(@"購(gòu)買(mǎi)失敗闸昨,未通過(guò)驗(yàn)證蚯斯!");
}
}
@end
最終服務(wù)端Token的返回字典:
{
environment = Sandbox;
receipt = {
"adam_id" = 0;
"app_item_id" = 0;
"application_version" = "1.0.2";
"bundle_id" = “FlyElephant”;
"download_id" = 0;
"in_app" = (
{
"is_trial_period" = false;
"original_purchase_date" = "2016-11-18 10:55:00 Etc/GMT";
"original_purchase_date_ms" = 1479466500000;
"original_purchase_date_pst" = "2016-11-18 02:55:00 America/Los_Angeles";
"original_transaction_id" = 1000000251845596;
"product_id" = “FlyElephant”;
"purchase_date" = "2016-11-18 10:55:00 Etc/GMT";
"purchase_date_ms" = 1479466500000;
"purchase_date_pst" = "2016-11-18 02:55:00 America/Los_Angeles";
quantity = 1;
"transaction_id" = 1000000251845596;
},
);
"original_application_version" = "1.0";
"original_purchase_date" = "2013-08-01 07:00:00 Etc/GMT";
"original_purchase_date_ms" = 1375340400000;
"original_purchase_date_pst" = "2013-08-01 00:00:00 America/Los_Angeles";
"receipt_creation_date" = "2016-12-09 10:31:52 Etc/GMT";
"receipt_creation_date_ms" = 1481279512000;
"receipt_creation_date_pst" = "2016-12-09 02:31:52 America/Los_Angeles";
"receipt_type" = ProductionSandbox;
"request_date" = "2016-12-09 10:31:56 Etc/GMT";
"request_date_ms" = 1481279516562;
"request_date_pst" = "2016-12-09 02:31:56 America/Los_Angeles";
"version_external_identifier" = 0;
};
status = 0;
}
效果圖:
FlyElephant.jpeg