2015-01-14 58 views
7

我在验证服务器端的苹果收据时遇到问题。 我试图在互联网上找到解决方案,但没有成功。苹果应用程序内购买收据 - 在服务器端进行验证

所以,说明: 首先,应用程序是为iOS7制作的。其次,我有几个项目(type = Non-Renewing Subscription)。所以用户可以购买一个或多个物品,然后他应该手动更新它们(再次购买)。

应用程序发送一个收据到服务器端,我向苹果发送一个请求,并得到很多 in_app收据的结果。例如:

"in_app":[ 
{ 
"quantity":"1", "product_id":"...", "transaction_id":"...", 
"original_transaction_id":"...", "purchase_date":"...", 
"purchase_date_ms":"...", "purchase_date_pst":"...", 
"original_purchase_date":"...", 
"original_purchase_date_ms":"...", "original_purchase_date_pst":"...", 
"is_trial_period":"..."}, 
{ 
"quantity":"1", "product_id":"...", 
"transaction_id":"...","original_transaction_id":"...", 
"purchase_date":"...", "purchase_date_ms":"...", 
"purchase_date_pst":"...", "original_purchase_date":"...", 
"original_purchase_date_ms":"...", "original_purchase_date_pst":"...", 
"is_trial_period":"..."} 
] 

因此,“in_app”中的每个“收据”都有transaction_id。但是,我如何识别当前购买的交易ID?我想验证它,并确保这是独一无二的。

我担心的是:如果有人能得到一个有效的收据,他将能够破解我们的服务器端API,并使用相同的有效收据进行无限数量的应用内购买。

我是否应该以某种方式解密并检查transaction_id中的“原始”收据,即我发送给Apple进行验证的收据?

任何帮助/建议将不胜感激。 预先感谢您。

问候, 马克西姆

+0

LOL我只是问同样的问题男人..我意外地发现这一点,看到你问了这个8小时前...这只是sux,我也没有线索也该怎么办所有这些收据...... – Adrian

+0

我想在这里做同样的检查。我希望有人看到并回答它! :\ – Adrian

+3

我认为关键是在* app *端获取当前购买的交易ID并将其与收据一起发送到服务器。您可以从事务对象获取应用程序端的事务ID。 –

回答

0

@Doug史密斯

https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html

如果你通过这个页面上的不同领域,你会发现

原来的事务标识符:: 对于恢复先前事务的事务,原始事务的事务标识符。否则,与事务标识符相同。 该值对应于原始事务的transactionIdentifier属性。 自动续订订阅续订链中的所有收据对该字段具有相同的值。

因此,对于您的非自动再生订阅,你要跟踪的两件事情在你的服务器端:

  1. 您与iTunes服务器验证收到的原始交易标识符,副教授这与您的数据库中的用户标识。
  2. 您从客户端收到的请求是“购买”还是“恢复购买”。

一旦你有你这两样东西,你可以写上这两个参数,如下面的逻辑:

::如果请求的类型是“购买”,并且你已经有了原始事务标识与其他用户ID相关联的收据,您可以阻止该购买。

::如果请求的类型是“恢复购买”,并且请求来自与原始事务标识符相关联的数据库中的相同用户标识,则允许他阻止其恢复。

此外,根据您的需要,您可以根据这些事情派生出自己的逻辑。

让我知道你是否有任何疑问。

+0

我的问题是'transaction_id'属性永远不会从收据JSON中的原始更新中更新。 –

+0

但是,您收到JSON中的两个两个字典。一个对应于您刚刚执行的交易的原始交易和另一个交易。 –

0

对于每个新的交易,苹果发送一个唯一的新收据,对其进行编码,以便无人可以伪造数据。

获取交易收据从已完成的交易编码,并将其发送到您的服务器,在服务器端进行解码并匹配与一个苹果发送到服务器。

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions 
{ 
    _transactionArray = transactions; 
    for (SKPaymentTransaction * transaction in transactions) 
    { 
     switch (transaction.transactionState) 
     { 
      case SKPaymentTransactionStatePurchased: { 
       NSData *receipt = transaction.transactionReceipt; 
       [self sendReceiptToServer]; 
      } break; 

      case SKPaymentTransactionStateFailed: { 
       // finish this transaction 
      } break; 

      case SKPaymentTransactionStateRestored: 
       NSData *receipt = transaction.transactionReceipt; 
       [self sendReceiptToServer:receipt]; 
      } break; 

      default: 
       break; 
     } 
    }; 
} 


-(void)sendReceiptToServer:(NSData *)receipt { 
    // encode receipt 
    // send receipt to server 
    // add success and error callback 
} 

-(void) receiptSuccess { 
    // finish transaction here 
} 

-(void) receiptError { 
    // try again sending receipt to server 
} 
+0

很少有什么问题,此代码: 1)' - [SKPaymentTransaction transactionReceipt]'被废弃了,因为iOS7,代替'[[一个NSBundle mainBundle] appStoreReceiptURL]'应该被使用。 2)交易应该完成,无论其完成状态如何,因此应在所有情况下调用'[SKPaymentQueue finishTransaction:]''(除缺省情况外)。 –

相关问题