<?php

/**
 * 接收IOS通知(支付结果)
 * @version
 *          1.0.0 Created at 2017-12-30. by --gwang
 * @author gwang (mail@wanggangzero.cn)
 * @copyright ? 2017-12-30, SJZ LoyalSoft Corporation & gwang. All rights reserved.
 *
 */
include_once __DIR__ . '/../../../main.php';                                    # 导入game utils
include_once __DIR__ . '/../Mo/resp.php';                                       # 导入通用返回值结构
include_once __DIR__ . '/../Mo/payRequest.php';                                 # 导入通用返回值结构
require_once __DIR__ . '/../Mo/OrderNotice.php';
require_once __DIR__ . '/config.ios.php';                                       # 配置文件, Ps. 里面用到了object

use loyalsoft\CLog;
use loyalsoft\HttpUtil;
use loyalsoft\pay\OrderNotice;
use loyalsoft\JsonUtil;

/**
 * 客户端参数
 */
class iosNotify {

    public $receipt;
    public $product_id;
    public $uid;
    public $cpOrderId;
    public $sandbox;
    public $callbackInfo;
    public $sign;
    public $notify_url;

    public function __construct($arr) {
        $this->receipt = $arr[0];
        $this->product_id = $arr[1];
        $this->uid = $arr[2];                           # 剥离一下前缀
        $this->cpOrderId = $arr[3];
        $this->sandbox = ($arr[4] == '否') ? false : true;                      # ☄,客户端竟然传的"是"和"否".
        $this->callbackInfo = $arr[5];
        $this->sign = $arr[6];
        $this->notify_url = $arr[7];
    }

}

/**
 * 到苹果后台进行支付凭证校验
 * @param str $receipt
 */
function VerifyFromApple($receipt, $sandbox, &$appleResp) {
    $cfg = config_for_ios::Inst($sandbox);
    $url = $cfg->verifySession_url;
    $ret = HttpUtil::makeRequest($url, JsonUtil::encode(array('receipt-data' => $receipt)));
    if ($ret['result']) { # 发送成功
        $data = JsonUtil::decode($ret['msg']);
        $in_app = $data->receipt->in_app[0];
        $appleResp = array(
            'status' => $data->status, //                                       # 收据状态
            'product_count' => $in_app->quantity, //                            # 收据->内购->数量
            'product_id' => $in_app->product_id, //                             # 收据->内购->道具编号
            'transaction_id' => $in_app->transaction_id, //                     # 收据->内购->交易编号
            'purchase_date' => $in_app->purchase_date, //                       # 收据->内购->购买时间
            'appid' => $data->receipt->app_item_id           //                 # 收据->appId(sandbox下为0)
        );

        if ($appleResp['status'] == 0) {                                        # 验证结果为 valid
            if ($appleResp['appid'] == $cfg->appid                              # Appid合法
                    || ($sandbox && $appleResp['appid'] == 0)) {                # 或者沙箱下面appid=0
                CLog::pay("[IOS.notify] Apple后台验证通过." . $ret['msg']);
                return true;
            } else {
                CLog::pay("[IOS.notify] 凭证的Appid不符!." . $ret['msg']);
            }
        } else {
            CLog::pay("[IOS.notify] Apple后台验证失败." . $ret['msg']);
        }
    } else {            # 通讯失败
        CLog::pay("[IOS.notify] 与Apple后台通讯失败.");
    }
    return false;
}

try {
    HttpUtil::PostOnly();
//    exit();

    CLog::pay("[IOS.notify] 收到支付回调请求: " . HttpUtil::getQueryString());
    $params = explode('&=&', HttpUtil::getQueryString());                       # 提取参数
    $notify = new iosNotify($params);
    $cfg = config_for_ios::Inst($notify->sandbox);                              # 配置信息
    CLog::pay($notify);
    $sign = md5($notify->cpOrderId . $cfg->appkey);                             # 计算签名md5(cpOrderId+appkey)
    CLog::pay("[IOS.notify] " . "[签名原文]:" . $notify->sign);
    CLog::pay("[IOS.notify] " . "[签名结果]:" . $sign);
    if ($sign != $notify->sign) {                                               # 验证签名
        exit(Resp::err(2, "Invalied sign!"));                                   # 退出
    }

    $appleResp = null;                                                          # 苹果的返回值
    if (!VerifyFromApple($notify->receipt, $notify->sandbox, $appleResp)) {     # 到苹果后台验证支付凭证
        exit(Resp::err(2, "Verify from apple server failed!"));                 # 退出
    }
    $order = OrderNotice::reParse_IOSOrder($notify, $appleResp);                # 将参数归一化到order
//    var_dump($order);
    if ($order != null) {
        if ($order->Check()) {                                                  # 订单校验
            if (!$order->CheckDuplicateSdkOrder()) {                            # 渠道订单编号校验，防重放（简单修改）攻击
                CLog::pay("[IOS.notify] [异常]:" . "重复的sdk_orderId！");                 # 日志
                exit(Resp::err(2, 'failure'));
            } else if ($order->status == 1) {                                   # 订单状态, 1代表支付成功
                $order->UpdateOrderStatus();                                    # 更新订单状态,->已付款
                CLog::pay("[IOS.notify] [发货] 订单: "                 # 日志
                        . $order->cpOrderId . ", 金额: " . $order->amount);
            } else if ($order->status == 2) {                                   # status为2(failed)的情况
                $order->UpdateOrderStatus();                                    # 直接更新订单状态,->支付失败
                CLog::pay("[IOS.notify] [不发货] 订单: " . $order->cpOrderId);
            } else {
                CLog::pay("[IOS.notify] [处理结果]: FAILURE (未知的支付状态)");  # 日志
                exit(Resp::err(1, '重试'));
            }
            CLog::pay("[IOS.notify] [处理结果]:" . "SUCCESS");         # 日志
            exit(Resp::ok('success'));
        }
    }
    CLog::pay("[IOS.notify] [处理结果]:" . "FAILURE");                 # 日志
    exit(Resp::err(2, 'failure'));
} catch (Exception $e) {
    CLog::pay("[IOS.notify] " . $e->getMessage());                    # 日志
    exit(Resp::err(1, $e->getMessage()));                                       # 未知异常, 告诉客户端可以重试
}