支付时拿到票据:

<?php
/*** POST验单curl* @param $post_data 请求参数['key'=>'value','keys'=>'values']* @param $url 请求地址* @return mixed*/public function post_receipt_data($post_data,$url){$curl = curl_init();curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);curl_setopt($curl, CURLOPT_POST, 1);$post_data = $post_data ? json_encode($post_data) : '';curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);if( !empty($aHeader) ){curl_setopt($curl, CURLOPT_HTTPHEADER, $aHeader);}curl_setopt($curl, CURLOPT_TIMEOUT, 120);curl_setopt($curl, CURLOPT_HEADER, 0);curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);$result = curl_exec($curl);$info = curl_getinfo($curl);$error_no = curl_errno($curl);$error_str = curl_error($curl);curl_close($curl);$result_array = json_decode($result,true);return $result_array;}/*** 苹果验单转发方法** apple地址:* https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html** @param $receipt 苹果票据* @param int $type 1:普通充值验单 2:支持传共享秘钥验单(不传则默认取订阅配置的秘钥)* @param null $url 请求地址* @param null $pwd 共享秘钥* @return mixed*/public function apple_validation_url($receipt,$type=1, $url=null, $pwd = null){$post_data['receipt-data'] = $receipt; //验单票据//增加共享秘钥参数if($type === 2){$post_data['password'] = !empty($pwd) ? $pwd :$this->my_config['apple_shared_secret_key'];$post_data['exclude-old-transactions'] = true; //true仅返回最新订阅信息}$url             = !empty($url) ? $url : "https://buy.itunes.apple.com/verifyReceipt"; //正式地址$test_verify_url = "https://sandbox.itunes.apple.com/verifyReceipt"; //测试环境地址$prod_verify_url = "https://buy.itunes.apple.com/verifyReceipt"; //生产环境地址$result_validation_info = $this->post_receipt_data($post_data, $url);switch ($result_validation_info['status']) {case 0: //正常break;case 21006: //订阅到期返回过期类票据break;case 21007: //沙盒模式的票据发送给了生产环境-重新转发给到测试地址$result_validation_info = $this->post_receipt_data($post_data, $test_verify_url);break;case 21008: //生产模式的票据发送给了测试环境-重新转发给到正式地址$result_validation_info = $this->post_receipt_data($post_data, $prod_verify_url);break;default: //记录错误日志//todo 写log弹出错误;\Common::response_error_header(403,"verify fail");}return $result_validation_info;}/*** 苹果验单数据解析(订阅类型返回结构体)* @param array $data 数据* @param int $type 结构体类型 1普通支付验单结构体 2订阅首次支付验单票据返回结构体 3apple订阅回调票据返回结构体* @return array*/public function apple_data_parsing(array $data = [],$type = 2){if (empty($data)) return $data; //没有数据if ($data['status'] != 0 && $data['status'] != 21006) return $data; //status不等于0$k= []; //返回结构体switch ($type){case 1: //普通验单结构$ks['status']  = $data['status'];$ks['receipt'] = $data['receipt'];unset($ks['receipt']['in_app']);$ks['receipt']['in_app'][0] = $data['receipt']['in_app'][0];//取in_app信息$k = array_merge($ks,$data['receipt']['in_app'][0]);break;case 2:$k['status']  = $data['status'];$k['receipt'] = $data['receipt'];unset($k['receipt']['in_app']);$k['pending_renewal_info'] = $data['pending_renewal_info'];//票据if(isset($data['latest_receipt'])){$k['latest_receipt'] = $data['latest_receipt'];}//如果存在值-降序取最新的数据-兼容返回全部订阅信息$latest = !empty($data['latest_receipt_info']) ? array_reverse($data['latest_receipt_info']) : [];//产品idif (isset($latest[0]['product_id'])) {$k['product_id'] = $latest[0]['product_id'];}//事件idif (isset($latest[0]['transaction_id'])) {$k['transaction_id'] = $latest[0]['transaction_id'];}//原始事件idif (isset($latest[0]['original_transaction_id'])) {$k['original_transaction_id'] = $latest[0]['original_transaction_id'];}//到期时间if (isset($latest[0]['expires_date_ms'])) {$k['expires_date'] = floor($latest[0]['expires_date_ms'] / 1000); //转换成时间戳 - 到期时间}//订阅状态if (isset($data['pending_renewal_info'][0]['auto_renew_status'])) {$k['auto_renew_status'] = $data['pending_renewal_info'][0]['auto_renew_status'];}break;case 3:$k['status']  = $data['status'];$k['receipt'] = $data['receipt'];//21006 apple返回到期票据返回结构体if($data['status'] == 21006 && !empty($data['latest_expired_receipt_info'])){$latest = $data['latest_expired_receipt_info'];}else{$latest = $data['latest_receipt_info'];}//票据if(isset($data['latest_receipt'])){$k['latest_receipt'] = $data['latest_receipt'];}//产品idif (isset($data['auto_renew_product_id']['product_id'])) {$k['product_id'] = $data['auto_renew_product_id']['product_id'];}//事件idif (isset($latest['transaction_id'])) {$k['transaction_id'] = $latest['transaction_id'];}//原始事件idif (isset($latest['original_transaction_id'])) {$k['original_transaction_id'] = $latest['original_transaction_id'];}//到期时间if (isset($latest['expires_date'])) {$k['expires_date'] = floor($latest['expires_date'] / 1000); //转换成时间戳 - 到期时间}//订阅状态if (isset($data['auto_renew_status'])) {$k['auto_renew_status'] = $data['auto_renew_status'];}break;default:return $data;}return $k;}?>

回调方法:

/*** ios订阅回调* ios_subscribe_callback* @annotation 同一个苹果appleID 购买的同一个商品的时 original_transaction_id 从始至终都是相同的*/public function iosSubscribeCallback(){$row_data = file_get_contents('php://input');if($row_data){$data = json_decode($row_data,true);switch ($data){case !empty($data['latest_receipt']): //最新票据$latest_receipt = $data['latest_receipt'];break;case !empty($data['latest_expired_receipt']): //最新过期票据$latest_receipt = $data['latest_expired_receipt'];break;default:$latest_receipt = $data['latest_receipt'];}if(!empty($latest_receipt)){//使用票据去苹果验单$receipt_info = $this->apple_validation_url($latest_receipt,2);$paper_a = $this->apple_data_parsing($receipt_info,3);//返回状态0 并且到期时间大于当前时间if($paper_a['status']==0 || $paper_a['status']==21006){//根据原始事件id查询没有关闭订阅服务的追她用户信息进行延期等操作//到期时间大于存储的到期时间if($paper_a['expires_date'] > $y['end_time'] && $paper_a['auto_renew_status'] == 1){//用户续费成功//todo 逻辑处理}else{//用户取消订阅状态if($paper_a['auto_renew_status']== 0){//todo逻辑处理}}}}else{\Common::response_error_header(403,'Invalid latest_receipt');}}else{//无效数据}\Common::response_success_header(200);exit;}

注意:回调时候比较坑的是他放票据的键名不是一样的。要对应取

PHP 苹果内购订阅验单函数,及其订阅回调处理案例相关推荐

  1. 苹果内购支付验签(php)

    苹果支付成功后走php验证支付结果 传receipt支付凭证 ( 自动订阅:所以需要增加一个参数: password: 秘钥, 就可以了, 但是官方文档说秘钥仅仅用在自动续订上面 大家叫后台加个验证, ...

  2. GooglePlay内购服务器验单

    相关后台配置见另外一篇文章 https://blog.csdn.net/wuyutaoktm/article/details/122450878 package mainimport ("c ...

  3. java(jfinal) 接入ios苹果内购(连续包月订阅),服务端将二次验证。

    大致流程: 1.ios端进行支付,然后收到苹果的一串数据(也叫收据),然后ios端将其转码为BASE64编码的字符串. 2.ios端请求服务端接口,将数据传给服务端,服务端拿到数据后,通过一系列处理后 ...

  4. 苹果内购开发总结(含掉单问题优化)

    1.后台查询充值记录 2018年3月27日 苹果内购开发(含掉单问题优化) 一.通用流程梳理 1.原来老的的流程(第七步有掉单风险) 第1. 先创建订单 第2.订单返回正常后(有订单号),启动苹果购买 ...

  5. 苹果内购-后端注意事项

    老大要收保护费,我等小弟那也没办法呀...是的,我说的就是苹果内购! 1.先上php验证函数: /*** 验证AppStore内付* @param string $receipt_data 付款后凭证 ...

  6. iOS内购(IAP)自动续订订阅

    一.介绍 iOS 的 App 内购类型有四种: 消耗型商品:只可使用一次的产品,使用之后即失效,必须再次购买. 示例:钓鱼 App 中的鱼食. 非消耗型商品:只需购买一次,不会过期或随着使用而减少的产 ...

  7. Cocos 2d-X Lua 游戏添加苹果内购(二) OC和Lua交互代码详解

    这是第二篇 Cocos 2d-X Lua 游戏添加苹果内购(一) 图文详解准备流程 这是前面的第一篇,详细的说明了怎样添加内购项目以及填写银行信息提交以及沙盒测试员的添加使用以及需要我们注意的东西,结 ...

  8. iOS:苹果内购实践

    iOS 苹果的内购 一.介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝等),当然开发 ...

  9. PHP后端处理苹果内购对接

    苹果内购流程: iOS App上次苹果商店审核对于虚拟金币类必须要用苹果支付,不能使用第三方支付,苹果支付还要3/7分成,呵呵... 1.前六步有IOS端处理,最终获取购买凭证 2.POST请求,发送 ...

最新文章

  1. 观点|基础模型产业发展路在何方?李飞飞等共话基础模型未来趋势
  2. php pdo获取查询数据_php使用PDO获取结果集的方法
  3. 安全与隐私没有允许任何来源选项
  4. oracle行迁移实验,Oracle 行迁移 amp; 行链接的检测与消除
  5. guava api_使用Google Guava的订购API
  6. 一台微型计算机_Linux的上百万行代码,一台新的微型计算机以及Google和Microsoft的更多产品
  7. 今日恐慌与贪婪指数为78 贪婪程度有所缓解
  8. HDOJ 2072 单词数
  9. 进程标识符及fork
  10. IOS开发之——屏幕适配-AutoLayout动画(05)
  11. oracle内连接和外连接
  12. oki5530sc打印错误_我用的是四通oki 5530sc针式打印机,打印时提示正在打印,但就是不打印...
  13. CSR867x — 蓝牙音频发射器方案(支持USB、模拟和SPDIF)
  14. 【翻译工具】如何复活谷歌翻译(网页翻译)
  15. 十六进制表示法(二进制/十六进制/十进制之间的转换)
  16. mysql驱动有什么用_什么是数据库驱动?
  17. 【物联网毕设基础】单片机:PCF8591 应用程序
  18. 《Unity 5.x游戏开发实战》一1.9 添加一个水平面
  19. RMAN维护:RMAN中的交叉校验crosscheck
  20. 微信小程序上传多张图片

热门文章

  1. 如何鼠标悬浮显示隐藏图片
  2. CentOS全版本 阿里云下载详细教程
  3. 为什么面试时面试官要问你有没有车贷,房贷和负债?
  4. PHP赛事贝格尔编排法--单循环
  5. 2017计算机考研参考书目推荐,2017年中山大学085211计算机技术考研参考书目推荐...
  6. metapath2vec 异构网络表示学习
  7. 通常人们说i5处理器的计算机其中二五是指,计算机cpu?学会看CPU只要五分钟
  8. java拆分list_Java 8 stream 流 拆分list
  9. 备份android分区,备份分区
  10. 向下取整符号_22. 为什么 Python 中的整除是向下取整?