APP内购流程
大致的业务逻辑是这样的
1. 程序通过bundle存储的plist文件得到产品标识符的列表。(从苹果网站后台下载产品列表,这个必须有)
2. 程序向App
Store发送请求,得到产品的信息。
3. App Store返回产品信息。
4. 程序把返回的产品信息显示给用户(App的store界面)
5. 用户选择某个产品
6. 程序向App
Store发送支付请求
7. App Store处理支付请求并返回交易完成信息。
8. App获取信息并提供内容给用户。
整个流程都是安全的,都是StoreKit和AppStore通信,需要的做的就是设置和回调接受结果就好
一.流程
首先登录到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 Info,Bank Info,Tax 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();
}
?>
没有评论:
发表评论