什么是內(nèi)購玛歌?
只要在iPhone App上購買的不是實物產(chǎn)品(也就是虛擬產(chǎn)品如qq幣.虎牙幣.電子書......) 都需要走內(nèi)購流程,蘋果在里面抽走三成。
使用內(nèi)購需要走的流程。
1,填寫協(xié)議,稅務(wù)和銀行業(yè)務(wù);
2,填寫用戶和職能; 創(chuàng)建內(nèi)購的項目
3,寫代碼,和后臺配合
4,添加項目內(nèi)購測試賬號;檢驗成果
具體步驟:
接下來的步驟特別繁瑣鲸阔,請做好準備澎剥。
一.填寫協(xié)議,稅務(wù)和銀行業(yè)務(wù)配置 https://itunesconnect.apple.com
1.請求合同
填寫地址信息
閱讀同意協(xié)議
2.填寫聯(lián)系方式
添加新的聯(lián)系人
選中聯(lián)系人
3.填寫銀行信息
添加銀行卡
選擇銀行卡所在國家
填寫銀行CNAPS Code
貨幣類型 CN###銀行賬號如果是對公的賬號叭首,需要填寫公司的英文名稱,如果沒有的話拼音
4.填寫稅務(wù)信息
U.S Tax Forms: 美國稅務(wù)
Australia Tax Forms:澳大利亞稅務(wù)
Canada Tax Forms: 加拿大稅務(wù)
第一個問題如下:詢問你是否是美國居民互广,有沒有美國伙伴關(guān)系或者美國公司敛腌,如果沒有直接選擇No。
第二個問題如下:詢問你有沒有在美國的商業(yè)性活動惫皱,沒有也直接選No
然后填寫你的稅務(wù)信息像樊,包括以下幾點:
Individual or Organization Name:個人或者組織名稱
Country of incorporation: 所在國家
Type of Beneficial Owner:受益方式,獨立開發(fā)者選個人
Permanent Residence:居住地址
Mailing address:郵寄地址
Name of Person Making this Declaration:聲明人
Title:頭銜
填寫完這些信息后就可以提交了
5.等待審核,時間24小時左右旅敷。
二.創(chuàng)建內(nèi)購項目
選中你要添加內(nèi)購項目的APP然后點擊功能,點擊+創(chuàng)建內(nèi)購項目生棍。
根據(jù)自己APP的需求選擇類型
填寫項目名稱id (ps:應(yīng)用在首次添加內(nèi)購買項目時需要與新的應(yīng)用版本一起提交審核。)
添加沙盒技術(shù)測試員
用戶職能>沙箱技術(shù)測試員
注意事項:
郵箱隨便寫但是格式要正確(test@163.com)媳谁,但是不能用已經(jīng)是AppleID的郵箱
App Store 地區(qū)不要亂選涂滴。雖然隨便哪個地區(qū)都可以用來測試(還沒上線之前app并沒有地區(qū)之分)友酱,但是在沙盒測試的時候,彈出的購買提示框會根據(jù)當前AppleID(沙盒賬號)的地區(qū)顯示語言的柔纵。
使用沙盒測試一定要用真機 (越獄的不行)
沙盒賬號不能直接登錄AppleStore登錄時會提示"不允許創(chuàng)建iTunes賬戶”
進行沙盒測試時需要退出AppleStore的賬號
三.代碼
#import <Foundation/Foundation.h>
#import "WXApi.h"
typedef NS_ENUM(NSInteger , Payment) {
IAP6 = 6,
IAP25 = 25,
IAP60 = 60
};
@interface PayCenter : NSObject
singleton_interface(PayCenter);
- (void)startInit;
- (void)payWithMoney:(NSInteger)money andType:(PayType)type dataDic:(NSDictionary *)dataDic;
@property (nonatomic, strong) MBProgressHUD * hud;
@property (nonatomic, copy) NSString * rechargeNumber;
@end
#define kProductID_IAP6 @"org.qqhl.nursning.6"http://6
#import "PayCenter.h"
#import "PayHttpRequest.h"
//#import "Order.h"
//#import "DataSigner.h"
//#import <AlipaySDK/AlipaySDK.h>
#import <StoreKit/StoreKit.h>
@interface PayCenter()<SKPaymentTransactionObserver,SKProductsRequestDelegate>
{
int buyType;
NSInteger _money;
}
@property (nonatomic, strong) NSMutableDictionary * dataDic;
@end
@implementation PayCenter
singleton_implementation(PayCenter);
- (void)startInit
{
[WXApi registerApp:kWeChatShareAppKey withDescription:appDefaultTilte];
}
- (void)payWithMoney:(NSInteger)money andType:(PayType)type dataDic:(NSDictionary *)dataDic
{
_money = money;
self.dataDic = [NSMutableDictionary dictionaryWithDictionary:dataDic];
switch (type) {
case PayTypeWX:
[self payTypeWXPay];
break;
case ApplePay:
// [self payTypeAliPay];
[[SKPaymentQueue defaultQueue]addTransactionObserver:self];
if ([SKPaymentQueue canMakePayments]) {
HULog(@"允許程序內(nèi)付費購買");
[self payTypeApplePay];
}else {
HULog(@"不允許程序內(nèi)付費購買");
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:@"提示"
message:@"您的手機沒有打開程序內(nèi)付費購買"
delegate:nil cancelButtonTitle:NSLocalizedString(@"關(guān)閉",nil) otherButtonTitles:nil];
[alerView show];
}
break;
default:
break;
}
}
- (void)payTypeApplePay{
NSLog(@"---------請求對應(yīng)的產(chǎn)品信息------------");
NSArray *product = nil;
switch (_money) {
case IAP6:
{
product=[[NSArray alloc] initWithObjects:kProductID_IAP6,nil];
NSLog(@"---------IAP6------------");
}
break;
case IAP25:
{
NSLog(@"---------IAP25------------");
}
break;
case IAP60:
{
NSLog(@"---------IAP60------------");
}
break;
default:
break;
}
NSSet *nsSet = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:nsSet];
request.delegate = self;
[request start];
}
#pragma mark - SKProductsRequestDelegate代理
//返回的在蘋果服務(wù)器請求的產(chǎn)品信息
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
HULog(@"收到產(chǎn)品信息");
NSArray *myProduct = response.products;
HULog(@"產(chǎn)品id %@",response.invalidProductIdentifiers);
NSLog(@"產(chǎn)品付費數(shù)量%d",(int)[myProduct count]);
//populate UI
for (SKProduct *product in myProduct) {
NSLog(@"product info");
NSLog(@"SKProduct 描述信息%@", [product description]);
NSLog(@"產(chǎn)品標題 %@" , product.localizedTitle);
NSLog(@"產(chǎn)品描述信息: %@" , product.localizedDescription);
NSLog(@"價格: %@" , product.price);
NSLog(@"Product id: %@" , product.productIdentifier);
}
SKPayment *payment = nil;
switch (_money) {
case IAP6:
{
payment = [SKPayment paymentWithProductIdentifier:kProductID_IAP6];
}
break;
case IAP25:{
}
default:
break;
}
NSLog(@"發(fā)起購買請求");
[[SKPaymentQueue defaultQueue]addPayment:payment];
}
//實現(xiàn)監(jiān)聽方法
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
NSLog(@"調(diào)用了幾次這個方法缔杉?");
SKPaymentTransaction *transaction = transactions.lastObject;
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased: {
NSLog(@"購買完成,向自己的服務(wù)器驗證 ---- %@", transaction.payment.applicationUsername);
NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
NSString *receipt = [data base64EncodedStringWithOptions:0];
// [self buySuccessWithReceipt:receipt transaction:transaction];
}
break;
case SKPaymentTransactionStateFailed: {
NSLog(@"交易失敗");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
break;
case SKPaymentTransactionStateRestored: {
NSLog(@"已經(jīng)購買過該商品");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
break;
case SKPaymentTransactionStatePurchasing: {
NSLog(@"商品添加進列表");
}
break;
default: {
NSLog(@"這是什么情況啊搁料?");
}
break;
}
}
@end```
####購買成功后需要跟服務(wù)器交互驗證交易是否成功
// 驗證憑據(jù)或详,獲取到蘋果返回的交易憑據(jù)
// appStoreReceiptURL iOS7.0增加的,購買交易完成后郭计,會將憑據(jù)存放在該地址
NSURL receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 從沙盒中獲取到購買憑據(jù)
NSData receipt = [NSData dataWithContentsOfURL:receiptURL];
// 傳輸?shù)氖荁ASE64編碼的字符串
/
BASE64 常用的編碼方案霸琴,通常用于數(shù)據(jù)傳輸,以及加密算法的基礎(chǔ)算法昭伸,傳輸過程中能夠保證數(shù)據(jù)傳輸?shù)姆€(wěn)定性
BASE64是可以編碼和解碼的
*/
NSDictionary *requestContents = @{
@"receipt-data": [receipt base64EncodedStringWithOptions:0]
};
NSError *error;
// 轉(zhuǎn)換為 JSON 格式
NSData requestData = [NSJSONSerialization dataWithJSONObject:requestContents
options:0
error:&error];
// 不存在
if (!requestData) { / ... Handle error ... */ }
// 發(fā)送網(wǎng)絡(luò)POST請求沈贝,對購買憑據(jù)進行驗證
NSString *verifyUrlString;
測試環(huán)境 verifyUrlString = @"https://sandbox.itunes.apple.com/verifyReceipt";
生產(chǎn)環(huán)境 verifyUrlString = @"https://buy.itunes.apple.com/verifyReceipt";
// 國內(nèi)訪問蘋果服務(wù)器比較慢,timeoutInterval 需要長一點
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:[[NSURL alloc] initWithString:verifyUrlString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
[storeRequest setHTTPMethod:@"POST"];
[storeRequest setHTTPBody:requestData];
// 在后臺對列中提交驗證請求勋乾,并獲得官方的驗證JSON結(jié)果
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:storeRequest queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
NSLog(@"鏈接失敗");
} else {
NSError *error;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (!jsonResponse) {
NSLog(@"驗證失敗");
}
// 比對 jsonResponse 中以下信息基本上可以保證數(shù)據(jù)安全
/*
bundle_id
application_version
product_id
transaction_id
*/
NSLog(@"驗證成功");
}
}];
}
[蘋果官方文檔](https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW4)
```剛接觸內(nèi)購如有不足之處請指教 ```