<?php
namespace Yurun\PaySDK\AlipayApp;
use Yurun\PaySDK\Base;
use Yurun\PaySDK\Lib\CertUtil;
use Yurun\PaySDK\Lib\Encrypt\AES;
use Yurun\PaySDK\Lib\ObjectToArray;
class SDK extends Base
{
public $publicParams;
public $alipayCertSn;
public $appCertSn;
public $alipayRootCertSn;
public function __construct($publicParams)
{
parent::__construct($publicParams);
if ($publicParams->usePublicKeyCert)
{
$this->alipayCertSn = CertUtil::getCertSN($publicParams->alipayCertPath);
$this->appCertSn = CertUtil::getCertSN($publicParams->merchantCertPath);
$this->alipayRootCertSn = CertUtil::getRootCertSN($publicParams->alipayRootCertPath);
}
}
public function __parseExecuteData($params, &$data, &$requestData, &$url)
{
$data = array_merge(ObjectToArray::parse($this->publicParams), ObjectToArray::parse($params));
unset($data['apiDomain'], $data['appID'], $data['businessParams'], $data['appPrivateKey'], $data['appPrivateKeyFile'], $data['appPublicKey'], $data['appPublicKeyFile'], $data['_syncResponseName'], $data['_method'], $data['_isSyncVerify'], $data['aesKey'], $data['isUseAES'], $data['alipayCertPath'], $data['alipayRootCertPath'], $data['merchantCertPath'], $data['usePublicKeyCert'], $data['_contentType']);
$data['app_id'] = $this->publicParams->appID;
$data['biz_content'] = $params->businessParams->toString();
if ($this->publicParams->isUseAES)
{
$data['biz_content'] = AES::encrypt($data['biz_content'], base64_decode($this->publicParams->aesKey));
}
if ($this->publicParams->usePublicKeyCert)
{
$data['app_cert_sn'] = $this->appCertSn;
$data['alipay_root_cert_sn'] = $this->alipayRootCertSn;
}
$data['timestamp'] = date('Y-m-d H:i:s');
$data['sign'] = $this->sign($data);
$requestData = $data;
$url = $this->publicParams->apiDomain;
}
public function sign($data)
{
$content = $this->parseSignData($data);
if (empty($this->publicParams->appPrivateKeyFile))
{
$key = $this->publicParams->appPrivateKey;
$method = 'signPrivate';
}
else
{
$key = $this->publicParams->appPrivateKeyFile;
$method = 'signPrivateFromFile';
}
switch ($this->publicParams->sign_type)
{
case 'RSA':
$result = \Yurun\PaySDK\Lib\Encrypt\RSA::$method($content, $key);
break;
case 'RSA2':
$result = \Yurun\PaySDK\Lib\Encrypt\RSA2::$method($content, $key);
break;
default:
throw new \Exception('未知的加密方式:' . $this->publicParams->sign_type);
}
return base64_encode($result);
}
public function verifyCallback($data)
{
if (!isset($data['sign'], $data['sign_type']))
{
return false;
}
$signType = $data['sign_type'];
unset($data['sign_type']);
$content = $this->parseSignData($data);
if (empty($this->publicParams->appPublicKeyFile))
{
$key = $this->publicParams->appPublicKey;
$method = 'verifyPublic';
}
else
{
$key = $this->publicParams->appPublicKeyFile;
$method = 'verifyPublicFromFile';
}
switch ($signType)
{
case 'RSA':
return \Yurun\PaySDK\Lib\Encrypt\RSA::$method($content, $key, base64_decode($data['sign']));
case 'RSA2':
return \Yurun\PaySDK\Lib\Encrypt\RSA2::$method($content, $key, base64_decode($data['sign']));
default:
throw new \Exception('未知的加密方式:' . $signType);
}
}
public function verifySync($params, $data, $response = null)
{
if (!isset($data['sign']))
{
return true;
}
if ($this->publicParams->usePublicKeyCert && $this->alipayCertSn !== (isset($data['alipay_cert_sn']) ? $data['alipay_cert_sn'] : null))
{
return false;
}
$content = json_encode($data[$params->_syncResponseName], \JSON_UNESCAPED_UNICODE);
if (empty($this->publicParams->appPublicKeyFile))
{
$key = $this->publicParams->appPublicKey;
$method = 'verifyPublic';
}
else
{
$key = $this->publicParams->appPublicKeyFile;
$method = 'verifyPublicFromFile';
}
switch ($this->publicParams->sign_type)
{
case 'RSA':
return \Yurun\PaySDK\Lib\Encrypt\RSA::$method($content, $key, base64_decode($data['sign']));
case 'RSA2':
return \Yurun\PaySDK\Lib\Encrypt\RSA2::$method($content, $key, base64_decode($data['sign']));
default:
throw new \Exception('未知的加密方式:' . $this->publicParams->sign_type);
}
}
public function parseSignData($data)
{
unset($data['sign']);
ksort($data);
$content = '';
foreach ($data as $k => $v)
{
if ('' !== $v && null !== $v && !\is_array($v))
{
$content .= $k . '=' . $v . '&';
}
}
return trim($content, '&');
}
public function execute($params, $format = 'JSON')
{
$result = parent::execute($params, $format);
if ($this->publicParams->isUseAES && isset($result[$params->_syncResponseName]))
{
$result[$params->_syncResponseName] = json_decode(AES::decrypt($result[$params->_syncResponseName], base64_decode($this->publicParams->aesKey)), true);
}
return $result;
}
protected function __checkResult($result)
{
if (!\is_array($result))
{
return false;
}
$result = reset($result);
return isset($result['code']) && 10000 == $result['code'] && !isset($result['sub_code']);
}
protected function __getError($result)
{
if (!\is_array($result))
{
return '';
}
$result = reset($result);
if (isset($result['sub_code']))
{
return $result['sub_msg'];
}
if (isset($result['code']) && 10000 != $result['code'])
{
return $result['msg'];
}
return '';
}
protected function __getErrorCode($result)
{
if (!\is_array($result))
{
return '';
}
$result = reset($result);
if (isset($result['sub_code']))
{
return $result['sub_code'];
}
if (isset($result['code']) && 10000 != $result['code'])
{
return $result['code'];
}
return '';
}
}