IOS内购 服务器端验证 (附php源码)(附App Store最新版receipt表单)

最近为公司的一款手游项目开发了一个苹果APP Store内购功能,参考CSDN上查找了一些资料,结合实际开发过程中所遇到的问题,做个总结。我做的是服务器端工作,关于前端的具体实现请参考其他博客。

功能需求:iPhone玩家通过app进入Apple App Store选择所购买的金币或者钻石,付费完成后给玩家充值。

验证流程:(采用服务器模式)

1.后台server获取APP Store中的商品配置(建议在前端也配置一份Products ID)

2.前端发送请求至App Store,获取Products的信息

3.App Store返回Product信息

4.前端使用这些信息,向用户显示一个商店界面,用户从中选择一种商品

5.前端向App Store发送购买请求

6.App Store处理该请求,并返回完成的购买t收据(receipt-data)

7.前端将receipt-data和玩家uid两个数据,用HttpPost方式发给后台的php服务器

8.后台写个php程序,接收前端的数据,并将receipt-data发给Apple Store(注:php代码见附录1

9.App Store解析后台发过去的receipt,并返回receipt,以及验证结果(是否合法)

10.后台php程序读取返回的receipt,并确定用户购买的product_id,记录交易订单号transacton_id(发给server存档,避免同一单号重复充值)(注:receipt表单详情见附录2

11.后台php程序将uid,product_id,transaction_id发给后台server,server负责给玩家充值,并通知前端充值成功

 

附录1(php服务端验证实现代码)

<?php
require_once("game.config.php");  //服务器配置 和 购买配置 ,请读者根据实际需要补充完整
require_once 'deliver.php';  //数据传送接口,负责PHP和游戏服务器之间的通信,请读者根据实际需要补充完整

$test_environment_url = 'https://sandbox.itunes.apple.com/verifyReceipt'; //测试环境URL
$production_environment_url = 'https://buy.itunes.apple.com/verifyReceipt'; //正式环境URL


$error_ios = 'verify success';
if(count($_POST) == 2 && !empty($_POST['receipt_data']) && !empty($_POST['uid']))
{
    $error = 0;
    $money = 0;
    $isSandbox = false;
    $post_url = null;
    $item_res = $item_Result['iosPay'];
    $item_id = 0;    
    $uid = intval($_POST['uid']);
    
    if($isSandbox)
    {
        $post_url = $test_environment_url;
    }
    else
    {
        $post_url = $production_environment_url;
    }
    
    $timeout = 10;
    $apple_receipt = $_POST['receipt_data'];
    $jsonData = array('receipt-data'=>$apple_receipt);
    $post_json = json_encode($jsonData);
        
    $log = date(DATE_RFC2822).'apple_receipt:'.$apple_receipt.chr(10);
    file_put_contents('./log/ios.log.'.date("Ymd"),$log,FILE_APPEND);
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $post_url);
    
    curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_json);
    curl_setopt($ch, CURLOPT_HEADER, 0);//设置header
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
    
    $response = curl_exec($ch);
    $con_error = curl_error($ch);
    curl_close($ch);

    
    $ret_data = json_decode($response, true);
//    $log = date(DATE_RFC2822).'ret_data_size:'.count($ret_data).chr(10);
//    file_put_contents('./log/ios.log.'.date("Ymd"),$log,FILE_APPEND);
    
    $status = $ret_data['status'];
    if($status != 0) //status 非0 购买失败
    {
        $error = $status;
        $error_ios = 'wrong status';
        $log = date(DATE_RFC2822).'status:'.$status.chr(10);
        file_put_contents('./log/ios.log.'.date("Ymd"),$log,FILE_APPEND);
    }
    
    if($error == 0)
    {
        $receipt = $ret_data['receipt'];

        $product_id = null;
        $transaction_id = null;

        if(array_key_exists('product_id',$receipt))
            $product_id = $receipt['product_id'];
        if(array_key_exists('transaction_id',$receipt))
            $transaction_id = (string)$receipt['transaction_id'];

        $log = date(DATE_RFC2822).'|uid:'.$uid.'|product_id:'.$product_id.'|transaction_id:'.$transaction_id.chr(10);
        file_put_contents('./log/ios.log.'.date("Ymd"),$log,FILE_APPEND); 

        if(array_key_exists($product_id,$ios_product_config) == true)
        {
            $item_id = intval($product_id);                 //服务器根据item_id充值
            $money = 1;                                               //此处money为固定值1,代表单次购买数量
        }
        if($money == 0 || $uid < 10000000)
        {
            $error = -1;
            $error_ios =  "no such productId:".$product_id."uid:".$uid;
        }
    }
    if($error == 0)
    {
        $payType = 'iosPay';
        $rst = Deliver::deliver_to_server(date('U'), '102', $uid, $item_id, $money, $payType, $transaction_id);    //发给服务器充值
        if($rst != true)
        {    
            $error_ios =  "send post msg to Server failed";
        }
    }
    $log = date(DATE_RFC2822).'/POST/'.$item_res.'/'.$error_ios.chr(10);
    file_put_contents('./log/ios.log.'.date("Ymd"),$log,FILE_APPEND);
}
else
{
    $error_ios = "error request format";
    $log = date(DATE_RFC2822).'/POST/'.$error_ios.chr(10);
    file_put_contents('./log/ios.log.'.date("Ymd"),$log,FILE_APPEND);
}

?>
 

附录2 (APP Store返回的最新receipt表单数据 18个字段)

original_purchase_date_pst 
purchase_date_ms 
unique_identifier 
original_transaction_id 
bvrs 
transaction_id //交易订单号,可传给服务器存档
quantity 
unique_vendor_identifier 
item_id 
version_external_identifier 
bid 
is_in_intro_offer_period 
product_id //商品id,前端需在APP Store 的开发者账号中配置,后台根据商品id匹配到具体的钻石或者金币
purchase_date 
is_trial_period 
purchase_date_pst 
original_purchase_date 
original_purchase_date_ms

//其他字段的具体含义请读者参考苹果IOS 内购的使用指南

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
以下是 PHP 代码实现 iOS 内购订单验证的示例: ```php <?php // 定义 app id 和 app secret $app_id = 'your_app_id'; $app_secret = 'your_app_secret'; // 获取验证请求参数 $receipt = $_POST['receipt']; $password = $_POST['password']; // 发送验证请求到 Apple 服务器 $url = 'https://buy.itunes.apple.com/verifyReceipt'; // 正式环境 //$url = 'https://sandbox.itunes.apple.com/verifyReceipt'; // 沙盒环境 $data = json_encode(array('receipt-data' => $receipt, 'password' => $password)); $options = array( 'http' => array( 'header' => "Content-type: application/json\r\n", 'method' => 'POST', 'content' => $data ) ); $context = stream_context_create($options); $result = file_get_contents($url, false, $context); // 解析验证结果 $response = json_decode($result, true); if ($response['status'] == 0) { // 验证成功 $latest_receipt_info = $response['latest_receipt_info']; $transaction_id = $latest_receipt_info[0]['transaction_id']; $product_id = $latest_receipt_info[0]['product_id']; $purchase_date = $latest_receipt_info[0]['purchase_date']; // TODO: 在这里处理订单验证成功后的逻辑 } else { // 验证失败 $error_code = $response['status']; $error_message = $response['status_message']; // TODO: 在这里处理订单验证失败后的逻辑 } ?> ``` 以上代码中,首先定义了 app id 和 app secret,然后获取了验证请求参数 receipt 和 password,接着发送验证请求到 Apple 服务器,并解析验证结果。如果验证成功,可以获取到订单的相关信息,如 transaction_id、product_id 和 purchase_date 等,可以在这里处理订单验证成功后的逻辑;如果验证失败,可以获取到错误码和错误信息,可以在这里处理订单验证失败后的逻辑。需要注意的是,验证请求需要发送到正式环境或者沙盒环境,根据实际情况选择相应的 URL 即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值