美文网首页
iOS内购 服务器端验证 (附php源码)(附App Store

iOS内购 服务器端验证 (附php源码)(附App Store

作者: 墨徕 | 来源:发表于2018-12-28 18:39 被阅读0次

    功能需求: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

    ---------------------

    作者:que_csdn

    来源:CSDN

    原文:https://blog.csdn.net/que_csdn/article/details/80861408

    版权声明:本文为博主原创文章,转载请附上博文链接!

    相关文章

      网友评论

          本文标题:iOS内购 服务器端验证 (附php源码)(附App Store

          本文链接:https://www.haomeiwen.com/subject/aapelqtx.html