2016年5月22日星期日

APP内购流程

APP内购流程

大致的业务逻辑是这样的
1. 程序通过bundle存储的plist文件得到产品标识符的列表。(从苹果网站后台下载产品列表,这个必须有)
2. 程序向App Store发送请求,得到产品的信息。
3. App Store返回产品信息。
4. 程序把返回的产品信息显示给用户(Appstore界面)
5. 用户选择某个产品
6. 程序向App Store发送支付请求
7. App Store处理支付请求并返回交易完成信息。
8. App获取信息并提供内容给用户。
    整个流程都是安全的,都是StoreKitAppStore通信,需要的做的就是设置和回调接受结果就好
.流程

首先登录到apple开发者中心点击进入我的App”. - >功能

左边第一项App内购项目.新建一个内购项目

选取您要创建的 App 内购买类型。如果缺少某个类型,请确保您已同意最新的付费应用程序协议。若要执行同意此协议操作,具有法务职能的用户必须前往协议、税务和银行业务。确保您在前往“协议、税务和银行业务”页面前已同意开发人员计划许可协议。您还应该确保您的 App 不受 App 内购买项目的欺诈,请查看 App 内购买收据验证文件。

App内购项目主要分为以下几项
1.消耗型项目
对于消耗型 App 内购买项目,用户每次下载时都必须进行购买。一次性服务通常属于消耗型项目,例如钓鱼 App 中的鱼饵。
2.非消耗型项目
对于非消耗型 App 内购买项目,用户仅需要购买一次。不会过期或随使用而减少的服务通常为非消耗型项目,例如游戏 App 的新跑道。
3.自动续订订阅
通过自动续订订阅,用户可以购买指定时间期限内的更新和动态内容。除非用户取消选择,否则订阅(例如杂志订阅等)会自动续订。
4.免费订阅
免费订阅是开发人员在“报刊杂志”中推广其内容的绝佳方式。用户注册免费订阅后,此订阅内容在与该用户 Apple ID 相关联的所有设备上可用。免费订阅不会过期,并且仅能在位于“报刊杂志”类别中的 App 中提供。
5.非续订订阅
非续订订阅允许有时限性的营销服务。对于 App 内购买项目中的限时访问内容,就需使用非续订订阅。例如,导航 App 中语音导航功能的一周订阅,或者年度订阅已存档的视频或音频的在线目录。


建立产品数据

*在提交 App 内购买项目以供审核前,您必须先上传屏幕快照。此屏幕快照仅用于审核目的,不会显示在 App Store 中。屏幕快照必须至少 312x390 像素,并且至少为 72 DPI

保存之后可以看到生成的信息


*协议、税务和银行业务,里面的Contact InfoBank InfoTax Info这三个信息填完整(少一个都不会拿到商品信息)
.代码
1. 工程中导入 StoreKit.Framework 框架
   在需要支付的vc #import<StoreKit/StoreKit.h>
2. - (void)viewDidLoad里添加购买监听
   [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

3. 检测是否允许内购
   if([SKPaymentQueue canMakePayments]){
            [selfrequestProductData:productID];       
   }else{
        NSLog(@"不允许程序内付费");       

   }

4.请求商品信息
   - (void)requestProductData:(NSString*)type{

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

NSSet*nsset = [NSSetsetWithArray:product];

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

request.delegate=self;    

[request start];

}
成功之后收到产品返回信息
-(void)productsRequest:(SKProductsRequest*)request didReceiveResponse:(SKProductsResponse *)response{
NSArray*product = response.products;
if([product count] ==0){
NSLog(@"没有商品");
return;
}
SKPayment * payment = [SKPayment paymentWithProduct:p];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
失败执行方法
- (void)request:(SKRequest*)request didFailWithError:(NSError*)error {
NSLog(@"商品信息请求错误:%@", error);
}
- (void)requestDidFinish:(SKRequest*)request {
NSLog(@"请求结束");
}

5.监听购买结果
-(void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray *)transaction {

for(SKPaymentTransaction *tranintransaction){

switch(tran.transactionState) {

caseSKPaymentTransactionStatePurchased:

NSLog(@"交易完成");

break;

caseSKPaymentTransactionStatePurchasing:

NSLog(@"商品添加进列表");

break;

caseSKPaymentTransactionStateRestored:

NSLog(@"已经购买过商品");

break;

caseSKPaymentTransactionStateFailed:

NSLog(@"交易失败");

break;

default:

[SVProgressHUDdismiss];

break;

}

*因为是去请求苹果的服务器,所以请求时间会稍微有点长

.测试

这个测试我也是挺呵呵的.构建测试版本到测试环境进行测试……..


demo实例(非官方提供)

其他博客整理仅供参考

.其他(服务端代码)
<?php 
    //服务器二次验证代码 
    function getReceiptData($receipt, $isSandbox = false)    
    {    
        if ($isSandbox) {    
            $endpoint = 'https://sandbox.itunes.apple.com/verifyReceipt';    
        }    
        else {    
            $endpoint = 'https://buy.itunes.apple.com/verifyReceipt';    
        }    

        $postData = json_encode(    
            array('receipt-data' => $receipt)    
        );    

        $ch = curl_init($endpoint);    
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);    
        curl_setopt($ch, CURLOPT_POST, true);    
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);    
       curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);  //这两行一定要加,不加会报SSL 错误 
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);  


        $response = curl_exec($ch);    
        $errno    = curl_errno($ch);    
        $errmsg   = curl_error($ch);    
        curl_close($ch);    
    //判断时候出错,抛出异常 
        if ($errno != 0) {    
            throw new Exception($errmsg, $errno);    
        }    

        $data = json_decode($response);    
    //判断返回的数据是否是对象 
        if (!is_object($data)) {    
            throw new Exception('Invalid response data');    
        }    
    //判断购买时候成功 
        if (!isset($data->status) || $data->status != 0) {    
            throw new Exception('Invalid receipt');    
        }    

    //返回产品的信息            
        return array(    
            'quantity'       =>  $data->receipt->quantity,    
            'product_id'     =>  $data->receipt->product_id,    
            'transaction_id' =>  $data->receipt->transaction_id,    
            'purchase_date'  =>  $data->receipt->purchase_date,    
            'app_item_id'    =>  $data->receipt->app_item_id,    
            'bid'            =>  $data->receipt->bid,    
            'bvrs'           =>  $data->receipt->bvrs    
        );    
    }    

    //获取 App 发送过来的数据,设置时候是沙盒状态 
        $receipt   = $_GET['data'];    
        $isSandbox = true;    
    //开始执行验证 
    try 
     { 
         $info = getReceiptData($receipt, $isSandbox);    
         // 通过product_id 来判断是下载哪个资源 
         switch($info['product_id']){ 
            case 'com.application.xxxxx.xxxx': 
                Header("Location:xxxx.zip"); 
            break;            
        } 
     } 
    //捕获异常 
    catch(Exception $e) 
    { 
        echo 'Message: ' .$e->getMessage(); 
    } 

?>

没有评论:

发表评论