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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342