苹果支付的流程:
1、前端在调起苹果支付前,先请求到服务端,服务端先生成一条充值记录,但是状态为:未支付;然后把这个订单id发给前端。
2、前端在支付完成的时候,会收到苹果的支付凭证,将此凭证和订单id回传给服务端。订单id的作用是用来确定是哪一笔。支付凭证是拿来校验是否支付成功。检验成功后,自己的业务逻辑(将该条订单的状态改为已支付,然后加余额或延长会员时间)
在这我也说一下我前端遇到的一个问题,方便有遇到的,可以参考。
直接编译到苹果手机上,会一直发起失败。我们这边的解决方法是,打包出来,然后发到苹果的【TestFlight】上,然后就可以正常发起了。
而且这时候发起的支付,可以无限支付,因为是沙盒环境,不会扣费
后端在苹果支付的过程中,只需要做两步操作:
第一步:生成一条充值记录,但是状态为:未支付
第二部:接收到前端的支付凭证后,校验支付凭证,然后业务逻辑
以下是苹果支付的验证。(创建订单的接口,不用特殊处理,只要生成一条未支付的订单记录就行(直接insert一条记录)。这里就不贴代码了)
<?php namespace appapicontroller; use appcommoncontrollerApi; class Applepay extends Api { protected $noNeedLogin = []; protected $noNeedRight = '*'; protected $orderNum = null; protected $model = null; protected $relationSearch = true; protected $appleCode = [ 21000 => 'App Store无法读取你提供的JSON数据', 21002 => '收据数据不符合格式', 21003 => '收据无法被验证', 21004 => '你提供的共享密钥和账户的共享密钥不一致', 21005 => '收据服务器当前不可用', 21006 => '收据是有效的,但订阅服务已经过期。当收到这个信息时,解码后的收据信息也包含在返回内容中', 21007 => '收据信息是测试用(sandbox),但却被发送到产品环境中验证', 21008 => '收据信息是产品环境中使用,但却被发送到测试环境中验证' ]; public function _initialize() { parent::_initialize(); $this->model = model('app\common\model\activity\Order'); } /** * @title 验证支付票据 完成订单接口 */ public function verifyReceipt() { $receipt = $this->request->param('receipt/s', ''); if (empty($receipt)) { $this->error('订单错误'); } $this->orderNum = $this->request->param('order_id/s', ''); $order = $this->model->where(array('order_id' => $this->orderNum))->find(); if (empty($order)) { $this->error('订单错误'); } if ($order['state'] == 1) { $this->error('订单已成功支付,请确认'); } $time = time(); file_put_contents("notifyLog/notifyProcessLog".date("Ymd", $time).".log", " " . date("Y-m-d H:i:s", $time) . ",支付凭证:" . $receipt, FILE_APPEND); $jsonItem = json_encode(['receipt-data' => $receipt]); $url = 'https://buy.itunes.apple.com/verifyReceipt'; //正式 //模拟post提交(下面会贴出来),将前端获取到的凭证,去和苹果换取详细的支付信息 $result = $this->http_post_json($jsonItem, $url); if ($result['status'] == '21007') { //验证失败 返回app错误状态 $url = 'https://sandbox.itunes.apple.com/verifyReceipt'; //测试 $result = $this->http_post_json($jsonItem, $url); } file_put_contents("notifyLog/notifyProcessLog".date("Ymd", $time).".log", " " . date("Y-m-d H:i:s", $time) . ",order:" . var_export($result, true), FILE_APPEND);
//如果检测到 等于 0 就是支付成功,其他的错误码去获取对应错误信息 if ($result['status'] !== 0) { //验证失败 返回app错误状态 $this->error($this->appleCode[$result['status']]); }
//接下来就是做自己的业务逻辑
$this->success('充值成功'); } //模拟post提交 public function http_post_json($json, $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $json); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //这两行一定要加,不加会报SSL 错误 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); $response = curl_exec($ch); $errno = curl_errno($ch); $errmsg = curl_error($ch); curl_close($ch); $data = json_decode($response, true); return $data; }
}
自己亲测可用。验证的步骤做的不够详细,可以自己根据逻辑详细做验证。
因为我只需要知道是否支付成功就行,所以我这只验证了前端传过来的支付成功的凭证是否正确且已正常支付,然后根据订单id定位哪条记录,就可以找到用户和金额。
(可根据自己的情况,加 product_id(苹果虚拟产品的id)的验证或其他的一些验证,此不再赘述)
!!!是的,你不用怀疑,就是这么简单~~~