<?php
defined('IN_WEB') or die('Include Error!');
/**
* Huawei本地支付
*/

class ModelPaymentos
{

    protected $_publicKey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuCYHagB12l6r2ls/K5VK5D0Bhv/97iFXhUnPK3huw5A727va6mMXVtveG9p21xYP32FndMh244HYS/K4Sd87joOotZurh+J3IgrOtFJEjvrUq48EnI0kG4b+Ne/MQ22kh5qG4AbYmzoynjdjKEKGKqILwS3z8mPCpmrvAl0kv7nJSfzZvAzwJCYeaV67wOkwdXgtitxLktuV8KN+Y3Ro7DzZFz3KDzONNdq1oI0Z/SDHsyobr2GFQLmjuWsjooqFzdlKbBKKkqN5F1WZNkJ7SMQX+gcUHBpOzxXqFGbAeQUWfCX/ugsx8xn19jeHx6TYyoYU4Vezr8u/QHtGHpphQQIDAQAB';
    private $appId = 100440289;
    private $error = [
        1 => 'Order Processing',
        2 => 'Payment Failed, Insufficient Balance',
        9 => 'Payment Failed'
    ];
    public function __construct()
    {

    }


    /**
     *	华为发货接口
     */
    public function deliveryHuaweiPay($param){
        if(empty($param)){
            return $this->responsePayment(98, 'PARAM ERROR');
        }
        //验证华为返回支付参数是否正确
        $ret = $this->validateHuaweiPay($param);
        if( !$ret ){
            return $this->responsePayment(1, 'SIGN ERROR');
        }

        //校验支付结果
        $orderId = $param['requestId'];//订单ID
        $productName = trim($param['productName']);//商品ID
        $tradeStatus = $param['result'];//支付结果 0：支付成功1：订单处理中（最终结果以后台通知为准，如有必要由应用调用queryPayment做漏单查询）2：支付失败，余额不足9：支付失败，其它错误
        $uin = $param['payType'];//支付类型:
//        $appId = $param['AppId'];//应用ID
        $consumeStreamId = $param['orderId'];

//        if(empty($appId) || $appId != $this->appId) {
//            oo::logs()->debug3('订单号:'.$orderId.'  uin:'.$uin.'  华为流水号:'.$consumeStreamId, 'hwPaymentFail.php');
//            return  $this->responsePayment(98, 'APPID ERROR');
//        }
        if($tradeStatus != 0) {
            $msg = $this->error[$tradeStatus] ?? 'Payment Failed';
            oo::logs()->debug3('支付错误码:'.$tradeStatus.'  订单号:'.$orderId.'  uin:'.$uin.'  华为流水号:'.$consumeStreamId, 'hwPaymentFail.php');
            return $this->responsePayment(99, $msg);
        }

        $dbGoods = oo::commonOprModel('goods')->getGoodsInfoByOrderId($orderId);
        if (empty($dbGoods)) {//验证商品对不对
            oo::logs()->debug3('商品错误  orderId:'.$orderId.' productId:'.$productName.'|  dbgoods:'.json_encode($dbGoods) . 'uin:'.$uin.'  华为流水号:'.$consumeStreamId,'hwPaymentFail.php');
            return $this->responsePayment(3, 'GOODS ERROR');
        }

        $uid = $dbGoods['uid'];
        $pubDeliveryRet = oo::commonOprModel('payment')->pubDelivery($uid, $orderId, $consumeStreamId);
        if( $pubDeliveryRet === true || $pubDeliveryRet === -3 ){//发货成功或者是已发货的订单，则返回正确
            return $this->responsePayment(0, 'SUCCESS');
        }
        return $this->responsePayment(99, 'DELIVERY FAIL');
    }


    /**
     * 返回消息到华为服务器
     * @param $errorCode int  错误码：0：失败    1：成功（已处理的请求也作为成功返回）  2：AppId无效  3：Act无效  4：参数无效   5：Sign无效  其他：应用自己定义，并在错误描述中体现
     * @param string $errMsg
     */
    private function responsePayment($errorCode, $errMsg = '')
    {
        $data['result'] = intval($errorCode);
//        $data['ErrorDesc'] = $errMsg;
        return $data;
    }

	/**
	*	验证华为支付
	*/
	protected function validateHuaweiPay($param)
	{
        if(empty($param)) {
            return false;
        }

        $signature = $param['sign'];
        unset($param['sign']);
        unset($param['signType']);

        $urlParam = $this->dealUrlParam($param);
        $valid = $this->verify($urlParam, $signature);
		if (!empty($valid)) {
            oo::logs()->debug3('valid:'.$valid.  'signature:'.$signature, 'hwPaymentVerifyFail.php');
			return false;
		}
		return true;
    }



    /**
     * 对参数进行处理
     * @param $data
     * @return string
     */
    protected function dealUrlParam($data)
    {
        $urlParam = '';
        //按ascii码升序排列
        ksort($data);
        $i = 0;
        foreach($data as $key=>$value)
        {
            if($key != "sign" && $key != "signType")
            {
                $urlParam .= ($i == 0 ? '' : '&').$key.'='.$value;
            }
            $i++;
        }
        return $urlParam;
    }


    /**
     * 使用RSA算法  SHA1WithRSA进行签名  --取消（SHA256WithRSA）
     * @param $data
     * @return string
     */
    protected function verify($data, $signature)
    {
//        oo::logs()->debug3("param:".$data.'  sign:'.$signature, 'hw_verify.php');
        $key = "-----BEGIN PUBLIC KEY-----\n".chunk_split( $this->_publicKey, 64, "\n" ).'-----END PUBLIC KEY-----';
        $key = openssl_get_publickey( $key );

        if ( empty( $key ) )
        {
            return 'Please pass a Base64-encoded public key from the Market portal';
        }
        $signature = str_replace('\\', '', $signature);
//        $signature = str_replace(' ', '+', $signature);
        $result = openssl_verify( $data, base64_decode( $signature ), $key, OPENSSL_ALGO_SHA256 );

        if ( 0 === $result )
        {
            oo::logs()->debug3('openssl error string:'.openssl_error_string()."\n".' 验签的参数:'.$data."\n".'  验签的signature:'.$signature, 'hw_verify.php');
            return 'fail to verify';
        }
        else if ( 1 !== $result )
        {
            return 'Unknown error verifying the signature in openssl_verify '.$result;
        }

        return '';
    }


}