<?php

/**
 * 接收华为后台通知(支付)
 * @version
 *          1.0.0 Created at 2018-3-1. by --gwang
 * @author gwang (mail@wanggangzero.cn)
 * @copyright ? 2018-3-1, 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 'config.huawei.php';                                               # 配置文件
// 签名算法

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

header("Content-Type: application/json; charset=utf-8");

/**
 * 华为验签算法
 * @param type $params
 * @return boolean
 */
function verify_sign_huawei($params)
{
    ksort($params);
    $sign = $params['sign'];
    $signType = isset($params['signType']) ? $params['signType'] : "RSA";  # 默认RSA
    $form = $params;
    unset($form['sign']);
    unset($form['signType']);
    if (empty($sign)) {
        return false;
    }

    $content = "";
    $i = 0;
    foreach ($form as $key => $value) {
        if ($key != "sign" && $key != "signType") {
            $content .= ($i == 0 ? '' : '&') . $key . '=' . $value;
        }
        $i++;
    }
    $pubKey = config_for_huawei::Inst()->getPubkey();
    $openssl_public_key = @openssl_get_publickey($pubKey);
    if (!$openssl_public_key) {
        return false;
    }
    $ok = @openssl_verify($content, base64_decode($sign), $openssl_public_key, $signType);
    @openssl_free_key($openssl_public_key);
    return $ok;
}

class OrderNotice_huawei extends OrderNotice
{

    static public function Parse($args)
    {
        $o = new OrderNotice();
        $o->callbackInfo = rawurldecode($args['extReserved']);                     # 透传参数, uid-uc,zoneid,cpOrderId
        $extArgs = explode(',', $o->callbackInfo);
        $o->channel = "huawei";                                                 # 渠道代码
        $o->cpOrderId = $args['requestId'];                                     # 订单编号
        $o->status = ($args["result"] == "0") ? 1 : 2;                          # 订单状态(华为返回值: 0/成功, 1. 退款成功(暂未启用), 其他失败)
        $o->uid = $extArgs[0]; // openid                                        # 玩家uid
        $o->amount = $args['amount'] * 100;                                     # 支付金额, 统一单位是分
        $o->sdk_orderid = $args['orderId'];                                     # 华为支付平台订单编号
//        $o->otherInfo = $args['notifyTime'];
        return $o;
    }

}

try {
    HttpUtil::PostOnly();                                                       # 华为那边肯定以POST方式来发送消息
    CLog::pay("[notify.华为] 收到支付回调请求: " . HttpUtil::getQueryString());
    $cfg = config_for_huawei::Inst();                                           # 配置信息
    $params = HttpUtil::getQueryParas();                                        # 提取参数
    if ($sign != verify_sign_huawei($params)) {                                 # 验证签名
        exit('{"result":1}');                                                   # 返回验签失败
    }
    $order = OrderNotice_huawei::Parse($params);                                # 将参数归一化到order
    if ($order != null) {
        if ($order->Check()) {                                                  # 订单校验, 1代表支付成功
            if ($order->status == 1) {                                          # 订单状态是成功
                $order->UpdateOrderStatus();                                    # 更新订单状态,->已付款
                CLog::pay("[notify.华为] [发货] 订单: " . $order->cpOrderId . ", 金额: " . $order->amount);
            } else if ($order->status == 2) {                                   # status为2(failed)的情况
                $order->UpdateOrderStatus();                                    # 直接更新订单状态,->支付失败
                CLog::pay("[notify.华为] [不发货] 订单: " . $order->cpOrderId);
            } else {
                echo 'FAILURE';
                CLog::pay("[notify.华为][处理结果]: FAILURE (未知的支付状态)");      # 日志
                return;
            }
            echo 'SUCCESS'; //返回给sdk server的响应内容
            CLog::pay("[notify.华为][处理结果]:" . "SUCCESS");    # 日志
            return;
        }
    }
    CLog::pay("[notify.华为][处理结果]:" . "FAILURE");            # 日志
    echo 'FAILURE'; //返回给sdk server的响应内容 ,对于重复多次通知失败的订单,请参考文档中通知机制。
    return;
} catch (Exception $e) {
    CLog::pay("[notify.华为]" . $e->getMessage());                    # 日志
    throw new exception($e->getMessage());
}