流程:
1、前端在调起苹果支付前,先请求到服务端,服务端先生成一条充值记录,但是状态为:未支付;然后把这个订单id发给前端。
2、前端在支付完成的时候,会收到苹果的支付凭证,将此凭证和订单id回传给服务端。订单id的作用是用来确定是哪一笔。支付凭证是拿来校验是否支付成功。检验成功后,自己的业务逻辑(将该条订单的状态改为已支付,然后加余额或延长会员时间)
在这我也说一下前端可能会遇到的一个问题,方便有遇到的,可以参考。
直接编译到苹果手机上,会一直发起失败。我们这边的解决方法是,打包出来,然后发到苹果的【TestFlight】上,然后就可以正常发起了。
而且这时候发起的支付,可以无限支付,因为是沙盒环境,不会扣费
后端在苹果支付的过程中,只需要做两步操作:
第一步:生成一条充值记录
第二部:接收到前端的支付凭证后,校验支付凭证,然后实现自己的业务逻辑
以下是苹果支付的验证。(创建订单的接口,不用特殊处理,只要生成一条未支付的订单记录就行(直接insert一条记录)。这里就不贴代码了)
<?php
#@YIN
namespace app\api\controller;
use app\common\controller\Api;
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", "\n" . 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", "\n" . 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;
}}
接下来主要就是自己的业务逻辑了,自己亲测可用。验证的步骤做的不够详细,可以自己根据逻辑详细做验证。最后祝大家都能写码无bug
因篇幅问题不能全部显示,请点此查看更多更全内容