Payios.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. <?php
  2. namespace app\api\controller;
  3. use app\common\controller\Api;
  4. use think\Db;
  5. use addons\epay\library\Service;
  6. /**
  7. * 充值配置与充值订单
  8. */
  9. class Payios extends Api
  10. {
  11. protected $noNeedLogin = ['auto_renewal_vip_notify'];
  12. protected $noNeedRight = ['*'];
  13. //vip ios用的
  14. public function vip_config_ios(){
  15. $list = Db::name('payvip_config_ios')->field('id,money,days,title,info,bundle_id,is_lianxu')->where('is_show',1)->order('weight asc,id asc')->select();
  16. $data['vipconfig'] = $list;
  17. $data['vip_endtime'] = model('wallet')->getWallet($this->auth->id,'vip_endtime');
  18. $data['is_vip'] = $data['vip_endtime'] > time() ? 1 : 0;
  19. $data['avatar'] = localpath_to_netpath($this->auth->avatar);
  20. $this->success('success',$data);
  21. }
  22. //vip用的,创建订单
  23. public function vip_recharge_ios(){
  24. $rc_id = input('rc_id',0);
  25. $platform = 'app';
  26. $uid = $this->auth->id;
  27. if(!$rc_id){
  28. $this->error('请选择会员套餐');
  29. }
  30. if(!$this->user_auth_limit()){
  31. $this->error('请先完成实名认证');
  32. }
  33. //赋值money
  34. $recharge_config = Db::name('payvip_config_ios')->where('id',$rc_id)->find();
  35. $money = $recharge_config['money'];
  36. if($money<=0)
  37. {
  38. $this->error('支付金额必须大于0');
  39. }
  40. if($money > 10000){
  41. $this->error('支付金额太大');
  42. }
  43. //创建订单
  44. $data = [];
  45. $data['user_id'] = $uid;
  46. $data['out_trade_no'] = createUniqueNo('V',$uid); // 数据库订单号加密
  47. $data['order_amount'] = $money;
  48. $data['createtime'] = time();
  49. $data['pay_type'] = 'ios';
  50. $data['platform'] = $platform;
  51. $data['order_status'] = 0;
  52. $data['table_name'] = 'vip_recharge';
  53. $data['table_id'] = 0;
  54. $data['args'] = json_encode(['days'=>$recharge_config['days']]);
  55. $data['bundle_id'] = $recharge_config['bundle_id'];
  56. $data['is_lianxu'] = $recharge_config['is_lianxu'];
  57. $orderid = Db::name('pay_order')->insertGetId($data);
  58. $this->success('success',$data['out_trade_no']);
  59. }
  60. ////////////////////////////////
  61. //金币充值
  62. public function gold_config_ios(){
  63. $list = Db::name('paygold_webcon_ios')->field('id,money,gold,bundle_id')->where('is_show',1)->order('weigh asc,id asc')->select();
  64. $data['goldconfig'] = $list;
  65. $wallet = model('wallet')->getWallet($this->auth->id);
  66. $data['wallet'] = $wallet;
  67. $data['money_to_gold'] = config('site.money_to_gold');
  68. $this->success('success',$data);
  69. }
  70. //充值金币 创建订单
  71. public function gold_recharge_ios(){
  72. $rc_id = input_post('rc_id',0);
  73. $pay_type = 'ios';
  74. $platform = 'app';
  75. $uid = $this->auth->id;
  76. if(!$rc_id){
  77. $this->error('请选择充值金额');
  78. }
  79. if(!$this->user_auth_limit()){
  80. $this->error('请先完成实名认证');
  81. }
  82. //赋值money
  83. $recharge_config = Db::name('paygold_webcon_ios')->where('id',$rc_id)->find();
  84. $money = $recharge_config['money'] ?: 0;
  85. $gold = $recharge_config['gold'] ?: 0;
  86. //
  87. if($money<=0)
  88. {
  89. $this->error('支付金额必须大于0');
  90. }
  91. if($money > 10000){
  92. $this->error('支付金额太大');
  93. }
  94. //创建订单
  95. $data['user_id'] = $uid;
  96. $data['out_trade_no'] = createUniqueNo('P',$uid); // 数据库订单号加密
  97. $data['order_amount'] = $money;
  98. $data['createtime'] = time();
  99. $data['pay_type'] = $pay_type;
  100. $data['platform'] = $platform;
  101. $data['order_status'] = 0;
  102. $data['table_name'] = 'gold_recharge';
  103. $data['table_id'] = 0;
  104. $data['args'] = json_encode(['gold'=>$gold]);
  105. $data['bundle_id'] = $recharge_config['bundle_id'];
  106. $orderid = Db::name('pay_order')->insertGetId($data);
  107. $this->success('success',$data['out_trade_no']);
  108. }
  109. ////////////////////////////////////////
  110. //订阅信息处理,续订情况下,单独分支方法
  111. public function expires(){
  112. //苹果订阅的验证收据
  113. $original_transaction_id = input('original_transaction_id','','trim');
  114. $receipt_data = input('apple_receipt', '', 'trim');
  115. $transaction_id = input('transaction_id', '', 'trim');
  116. if (!$receipt_data || !$original_transaction_id || !$transaction_id) {
  117. $this->error('缺少参数');
  118. }
  119. filePut("\r\n\r\n".'新请求VIP订阅');
  120. $prefix = 'iosVIP订阅'.',传入original_transaction_id:'.$original_transaction_id.',传入transaction_id:'.$transaction_id.'。';
  121. filePut($prefix.'参数apple_receipt:'.$receipt_data);
  122. //检查重复订单
  123. $check_map = [
  124. 'original_transaction_id' => $original_transaction_id,
  125. 'transaction_id' => $transaction_id,
  126. ];
  127. $check_order = Db::name('user_vipxufei_task')->where($check_map)->field('id')->find();
  128. if($check_order){
  129. filePut($prefix.'续费早已完成');
  130. $this->success('充值已完成');
  131. }
  132. Db::startTrans();
  133. //查找订单
  134. $order_map = [
  135. 'original_transaction_id' => $original_transaction_id,
  136. ];
  137. $order_info = Db::name('user_vipxufei_task')->where($order_map)->order('expires_date_ms desc')->lock(true)->find();
  138. if (!$order_info) {
  139. Db::rollback();
  140. filePut($prefix.'不存在的订单');
  141. $this->error('不存在的订单');
  142. }
  143. // 验证支付状态
  144. $result = $this->validate_apple_pay($receipt_data);
  145. if (!$result['status']) {// 验证不通过
  146. Db::rollback();
  147. filePut($prefix.'验证'.$result['message']);
  148. $this->error($result['message']);
  149. }
  150. $in_app = $result['data']['receipt']['in_app'];
  151. $only_trans = [];
  152. foreach($in_app as $key => $trans){
  153. //非订阅信息,原始信息,不验证product_id因为可能换了新的套餐
  154. if($trans['transaction_id'] == $transaction_id && $original_transaction_id == $trans['original_transaction_id']/* && $trans['product_id'] == $order_info['bundle_id']*/){
  155. $only_trans = $trans;
  156. break;
  157. }
  158. }
  159. if(empty($only_trans)){
  160. Db::rollback();
  161. filePut($prefix.'未找到匹配的交易');
  162. $this->error('未找到匹配的交易');
  163. }
  164. //续订,但是换了产品了,重新定义order_info
  165. $order_info_bundle_id = $order_info['bundle_id'];
  166. if($only_trans['product_id'] != $order_info['bundle_id']){
  167. $pay_order_map = [
  168. 'user_id' => $this->auth->id,
  169. 'bundle_id' => $only_trans['product_id'],
  170. 'order_status' => 0,
  171. 'table_name' => 'vip_recharge',
  172. ];
  173. $pay_order = Db::name('pay_order')->where($pay_order_map)->order('id desc')->lock(true)->find();
  174. if(!$pay_order){
  175. Db::rollback();
  176. filePut($prefix.'未找到匹配的交易,新订单找不到');
  177. $this->error('未找到匹配的新订单');
  178. }
  179. // 修改订单状态
  180. $update_order = [
  181. 'notifytime'=>time(),
  182. 'order_status'=>1,
  183. 'original_transaction_id' => $only_trans['original_transaction_id'],
  184. 'in_app_one' => json_encode($only_trans),
  185. ];
  186. $ros = Db::name('pay_order')->where(['id' => $pay_order['id']])->update($update_order);
  187. if($ros === false) {
  188. filePut($prefix.'修改订单状态失败');
  189. Db::rollback();
  190. $this->error('充值失败');
  191. }
  192. $args = json_decode($pay_order['args'],true);
  193. //修改order_info
  194. $order_info['order_id'] = $pay_order['id'];
  195. $order_info['user_id'] = $pay_order['user_id'];
  196. $order_info['bundle_id'] = $pay_order['bundle_id'];
  197. $order_info['days'] = $args['days'];
  198. $order_info['original_transaction_id'] = $only_trans['original_transaction_id'];//多余
  199. }
  200. //验证时间,不得小于最新的一条预定信息
  201. if($only_trans['purchase_date_ms'] <= $order_info['purchase_date_ms'] || $only_trans['expires_date_ms'] <= $order_info['expires_date_ms']){
  202. Db::rollback();
  203. filePut($prefix.'时间对不上,返回成功,finish掉');
  204. $this->success(1);
  205. }
  206. //逻辑开始
  207. //先充值
  208. $user_info = Db::name('user_wallet')->where('user_id',$order_info['user_id'])->lock(true)->find();
  209. if($user_info['vip_endtime'] < time()){
  210. //过期了
  211. $vip_endtime = time() + (intval($order_info['days']) * 86400);
  212. }else{
  213. //追加vip
  214. $vip_endtime = $user_info['vip_endtime'] + (intval($order_info['days']) * 86400);
  215. }
  216. $update_data = [
  217. 'vip_endtime'=>$vip_endtime,
  218. ];
  219. $result = Db::name('user_wallet')->where('user_id',$order_info['user_id'])->update($update_data);
  220. if($result === false)
  221. {
  222. filePut($prefix.'逻辑续费vip时间失败');
  223. Db::rollback();
  224. $this->error('充值失败');
  225. }
  226. //逻辑结束
  227. //添加新的一个task
  228. $task_data = $order_info;
  229. unset($task_data['id']);
  230. $task_data['createtime'] = time();
  231. $task_data['apple_receipt'] = $receipt_data;
  232. $task_data['in_app_one'] = json_encode($only_trans);
  233. $task_data['transaction_id'] = $transaction_id;
  234. $task_data['times'] = $order_info['times'] + 1;
  235. $task_data['original_purchase_date_ms'] = $only_trans['original_purchase_date_ms'];
  236. $task_data['purchase_date_ms'] = $only_trans['purchase_date_ms'];
  237. $task_data['expires_date_ms'] = $only_trans['expires_date_ms'];
  238. if($only_trans['product_id'] != $order_info_bundle_id){
  239. $task_data['times'] = 1;//回归1
  240. }
  241. $task_id = Db::name('user_vipxufei_task')->insertGetId($task_data);
  242. if(!$task_id)
  243. {
  244. filePut($prefix.'用户添加vipxufei_task失败');
  245. Db::rollback();
  246. $this->error('充值失败');
  247. }
  248. Db::commit();
  249. filePut($prefix.'充值成功');
  250. $this->success('充值成功');
  251. //逻辑结束
  252. }
  253. //金币+vip,苹果内购支付回调,app请求的接口
  254. public function gold_notify_iosnew(){
  255. $original_transaction_id = input('original_transaction_id','','trim');
  256. if(!empty($original_transaction_id)){
  257. //订阅信息
  258. $this->expires();
  259. }
  260. //苹果内购的验证收据
  261. $receipt_data = input('apple_receipt', '', 'trim');
  262. $out_trade_no = input('out_trade_no', '', 'trim');
  263. $transaction_id = input('transaction_id', '', 'trim');
  264. if (!$receipt_data || !$out_trade_no || !$transaction_id) {
  265. $this->error('缺少参数');
  266. }
  267. filePut("\r\n\r\n".'新请求');
  268. $prefix = 'ios充值,登录user_id:'.$this->auth->id.',out_trade_no:'.$out_trade_no.',传入transaction_id:'.$transaction_id.'。';
  269. filePut($prefix.'参数apple_receipt:'.$receipt_data);
  270. Db::startTrans();
  271. // 查找订单
  272. $order_map = [
  273. // 'user_id' => $this->auth->id,
  274. 'out_trade_no' => $out_trade_no,
  275. ];
  276. $order_info = Db::name('pay_order')->where($order_map)->lock(true)->find();
  277. if (!$order_info) {
  278. Db::rollback();
  279. filePut($prefix.'不存在的订单');
  280. $this->error('不存在的订单');
  281. }
  282. if ($order_info['order_status'] == 1) {
  283. Db::rollback();
  284. filePut($prefix.'充值早已完成');
  285. $this->success('充值已完成');
  286. }
  287. // 验证支付状态
  288. $result = $this->validate_apple_pay($receipt_data);
  289. if (!$result['status']) {// 验证不通过
  290. Db::rollback();
  291. filePut($prefix.'验证'.$result['message']);
  292. $this->error($result['message']);
  293. }
  294. $in_app = $result['data']['receipt']['in_app'];
  295. $only_trans = [];
  296. foreach($in_app as $key => $trans){
  297. //非订阅信息,原始信息
  298. // $trans['transaction_id'] == $transaction_id 这个不重要,重要的是后面2个。应该也重要,保证这次处理的是初始交易
  299. if($trans['transaction_id'] == $transaction_id && $transaction_id == $trans['original_transaction_id'] && $trans['product_id'] == $order_info['bundle_id']){
  300. $only_trans = $trans;
  301. break;
  302. }
  303. }
  304. if(empty($only_trans)){
  305. Db::rollback();
  306. filePut($prefix.'未找到匹配的交易,产品id'.$order_info['bundle_id'].',原始交易id'.$transaction_id);
  307. $this->error('未找到匹配的交易,产品id'.$order_info['bundle_id'].',原始交易id'.$transaction_id);
  308. }
  309. /*
  310. $count = count($result['data']['receipt']['in_app']);
  311. $use_count = $count - 1;
  312. $product_id = $result['data']['receipt']['in_app'][$use_count]['product_id'];
  313. $my_transaction_id = $result['data']['receipt']['in_app'][$use_count]['transaction_id'];
  314. if($product_id != $order_info['bundle_id']){
  315. Db::rollback();
  316. filePut($prefix.'验证'.'非法请求,请立刻停止product_id:'.$product_id.'!='.$order_info['bundle_id']);
  317. $this->error('非法请求,请立刻停止,产品id错误');
  318. }
  319. if($my_transaction_id != $transaction_id){
  320. Db::rollback();
  321. filePut($prefix.'验证'.'非法请求,请立刻停止transaction_id:'.$my_transaction_id.'!='.$transaction_id);
  322. $this->error('非法请求,请立刻停止,交易id错误');
  323. }*/
  324. //逻辑开始
  325. $args = json_decode($order_info['args'],true);
  326. //先充值
  327. if($order_info['table_name'] == 'gold_recharge'){
  328. $result = model('Wallet')->lockChangeAccountRemain($order_info['user_id'],'gold',$args['gold'],10, '金币充值','pay_order',$order_info['id']);
  329. if($result['status']===false)
  330. {
  331. filePut($prefix.'逻辑添加金币失败');
  332. Db::rollback();
  333. $this->error('充值失败');
  334. }
  335. }
  336. //先充值
  337. if($order_info['table_name'] == 'vip_recharge'){
  338. $user_info = Db::name('user_wallet')->where('user_id',$order_info['user_id'])->lock(true)->find();
  339. if($user_info['vip_endtime'] < time()){
  340. //过期了
  341. $vip_endtime = time() + (intval($args['days']) * 86400);
  342. }else{
  343. //追加vip
  344. $vip_endtime = $user_info['vip_endtime'] + (intval($args['days']) * 86400);
  345. }
  346. $update_data = [
  347. 'vip_endtime'=>$vip_endtime,
  348. ];
  349. $result = Db::name('user_wallet')->where('user_id',$order_info['user_id'])->update($update_data);
  350. if($result === false)
  351. {
  352. filePut($prefix.'逻辑续费vip时间失败');
  353. Db::rollback();
  354. $this->error('充值失败');
  355. }
  356. //订阅vip需要多加的逻辑
  357. if($order_info['is_lianxu'] == 1){
  358. $task_data = [
  359. 'order_id' => $order_info['id'],
  360. 'user_id' => $order_info['user_id'],
  361. 'bundle_id' => $order_info['bundle_id'],
  362. 'days' => $args['days'],
  363. 'createtime' => time(),
  364. 'apple_receipt' => $receipt_data,
  365. 'in_app_one' => json_encode($only_trans),
  366. 'original_transaction_id' => $only_trans['original_transaction_id'],
  367. 'transaction_id' => $only_trans['transaction_id'],
  368. 'status' => 1,
  369. 'times' => 1,
  370. //'notification_type' => 'INITIAL_BUY'.',首次订阅',
  371. 'original_purchase_date_ms' => $only_trans['original_purchase_date_ms'],
  372. 'purchase_date_ms' => $only_trans['purchase_date_ms'],
  373. 'expires_date_ms' => $only_trans['purchase_date_ms'], //第一次借用购买时间戳
  374. ];
  375. $task_id = Db::name('user_vipxufei_task')->insertGetId($task_data);
  376. if(!$task_id)
  377. {
  378. filePut($prefix.'用户添加vipxufei_task失败');
  379. Db::rollback();
  380. $this->error('充值失败');
  381. }
  382. }
  383. }
  384. // 修改订单状态
  385. $update_order = [
  386. 'notifytime'=>time(),
  387. 'order_status'=>1,
  388. 'original_transaction_id' => $only_trans['original_transaction_id'],//理论上与 transaction_id 相等
  389. 'in_app_one' => json_encode($only_trans),
  390. ];
  391. $ros = Db::name('pay_order')->where(['id' => $order_info['id']])->update($update_order);
  392. if($ros === false) {
  393. filePut($prefix.'修改订单状态失败');
  394. Db::rollback();
  395. $this->error('充值失败');
  396. }
  397. Db::commit();
  398. filePut($prefix.'充值成功');
  399. $this->success('充值成功');
  400. //逻辑结束
  401. }
  402. ////////////////////////////////////
  403. //苹果自动扣费回调,server to server
  404. public function auto_renewal_vip_notify(){
  405. $this->notify_log_start('ios');
  406. }
  407. ////////////////////////////////私有方法///////////////////////////////////////////////////////////////
  408. //异步日志
  409. private function notify_log_start($paytype = 'ios'){
  410. //记录支付回调数据
  411. ignore_user_abort(); // run script in background
  412. set_time_limit(30);
  413. // 日志文件 start
  414. $log_base_dir = '../paylog/'.$paytype.'/';
  415. if (!is_dir($log_base_dir))
  416. {
  417. mkdir($log_base_dir, 0770, true);
  418. @chmod($log_base_dir, 0770);
  419. }
  420. $notify_file = $log_base_dir.'notify.txt';
  421. if(!file_exists($notify_file)) {
  422. @touch($notify_file);
  423. @chmod($notify_file, 0770);
  424. }
  425. if(filesize($notify_file)>5242880)//大于5M自动切换
  426. {
  427. rename($notify_file, $log_base_dir.'notify_'.date('Y_m_d_H_i_s').'.txt');
  428. }
  429. if(!file_exists($notify_file)) {
  430. @touch($notify_file);
  431. @chmod($notify_file, 0770);
  432. }
  433. // 日志文件 end
  434. //开始写入
  435. $_REQUEST = isset($_REQUEST) ? $_REQUEST : array();
  436. if($_REQUEST && $paytype == 'alipay') {
  437. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收request]".json_encode($_REQUEST), FILE_APPEND);
  438. } else {
  439. $xml = file_get_contents("php://input");
  440. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流原始数据] \n".$xml, FILE_APPEND);
  441. $xmlObj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
  442. file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流] ".json_encode($xmlObj), FILE_APPEND);
  443. }
  444. ini_set('display_errors','On');
  445. return $notify_file;
  446. }
  447. public function test(){
  448. $a = input('apple_receipt');
  449. $b = $this->validate_apple_pay($a);
  450. dump($b);
  451. }
  452. /**
  453. * 验证AppStore内付
  454. * @param string $receipt_data 付款后凭证
  455. * @return array 验证是否成功
  456. */
  457. function validate_apple_pay($receipt_data = '') {
  458. // 验证参数
  459. if (strlen($receipt_data) < 20) {
  460. $result = array(
  461. 'status' => false,
  462. 'message' => '非法参数'
  463. );
  464. return $result;
  465. }
  466. // 请求验证
  467. $html = $this->curl($receipt_data);
  468. $data = json_decode($html, true);
  469. $data['sandbox'] = '0';
  470. // p($data);die;
  471. if ($data['status'] == '21002') {
  472. $result = array(
  473. 'status' => false,
  474. 'message' => 'status:21002'
  475. );
  476. return $result;
  477. }
  478. // 如果是沙盒数据 则验证沙盒模式 21008;正式数据 21007
  479. if ($data['status'] == '21007') {
  480. // 请求验证
  481. $html = $this->curl($receipt_data, 1);
  482. $data = json_decode($html, true);
  483. $data['sandbox'] = '1';
  484. }
  485. if (isset($_GET['debug'])) {
  486. exit(json_encode($data));
  487. }
  488. if ($data['receipt']['bundle_id'] != 'com.huxiu.tken') {
  489. $result = array(
  490. 'status' => false,
  491. 'message' => '非法请求',
  492. 'data' => $data
  493. );
  494. return $result;
  495. }
  496. // 判断是否购买成功
  497. if (intval($data['status']) === 0) {
  498. $result = array(
  499. 'status' => true,
  500. 'message' => '购买成功',
  501. 'data' => $data
  502. );
  503. } else {
  504. $result = array(
  505. 'status' => false,
  506. 'message' => '购买失败 status:' . $data['status']
  507. );
  508. }
  509. // dump($result);
  510. return $result;
  511. }
  512. /**
  513. * 0 票据校验成功
  514. * 21000 App Store不能读取你提供的JSON对象25
  515. * 21002 receipt-data域的数据有问题
  516. * 21003 receipt无法通过验证
  517. * 21004 提供的shared secret不匹配你账号中的shared secret
  518. * 21005 receipt服务器当前不可用
  519. * 21006 receipt合法,但是订阅已过期。服务器接收到这个状态码时,receipt数据仍然会解码并一起发送
  520. * 21007 receipt是Sandbox receipt,但却发送至生产系统的验证服务
  521. * 21008 receipt是生产receipt,但却发送至Sandbox环境的验证服务
  522. */
  523. //苹果也是建议这个校验逻辑由服务端完成。服务器需要先去请求正式环境。如果receipt是正式环境的,那么这个时候苹果会返回(21007)告诉我们这个是沙盒的receipt,那么服务器再去请求sandbox环境。
  524. function curl($receipt_data,$sandbox = 0) {
  525. //小票信息
  526. $POSTFIELDS = [
  527. 'receipt-data' => $receipt_data,
  528. 'password' => '09ef214173a944808ac648b15fa02167'
  529. ];
  530. $POSTFIELDS = json_encode($POSTFIELDS, 320);
  531. //正式购买地址 沙盒购买地址
  532. $url_buy = "https://buy.itunes.apple.com/verifyReceipt";
  533. $url_sandbox = "https://sandbox.itunes.apple.com/verifyReceipt";
  534. //默认后台控制
  535. if (config('site.ios_pay_sandbox') > 0 ) {
  536. $url = $url_buy;
  537. } else {
  538. $url = $url_sandbox;
  539. }
  540. //强制沙盒
  541. if($sandbox == 1){
  542. $url = $url_sandbox;
  543. }
  544. $ch = curl_init($url);
  545. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  546. curl_setopt($ch, CURLOPT_POST, true);
  547. curl_setopt($ch, CURLOPT_POSTFIELDS, $POSTFIELDS);
  548. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //这两行一定要加,不加会报SSL 错误
  549. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  550. $response = curl_exec($ch);
  551. $errno = curl_errno($ch);
  552. curl_close($ch);
  553. if ($errno != 0) {
  554. return $errno;
  555. } else {
  556. return $response;
  557. }
  558. }
  559. }