<?php
namespace Alipay\EasySDK\Kernel;
use Alipay\EasySDK\Kernel\Util\AES;
use Alipay\EasySDK\Kernel\Util\JsonUtil;
use Alipay\EasySDK\Kernel\Util\PageUtil;
use Alipay\EasySDK\Kernel\Util\SignContentExtractor;
use Alipay\EasySDK\Kernel\Util\Signer;
use AlibabaCloud\Tea\FileForm\FileForm;
use AlibabaCloud\Tea\FileForm\FileForm\FileField;
use GuzzleHttp\Psr7\Stream;
use Psr\Http\Message\ResponseInterface;
class EasySDKKernel
{
private $config;
private $optionalTextParams;
private $optionalBizParams;
private $textParams;
private $bizParams;
public function __construct($config)
{
$this->config = $config;
}
public function injectTextParam($key, $value)
{
if ($key != null) {
$this->optionalTextParams[$key] = $value;
}
}
public function injectBizParam($key, $value)
{
if ($key != null) {
$this->optionalBizParams[$key] = $value;
}
}
public function getTimestamp()
{
return date("Y-m-d H:i:s");
}
public function getConfig($key)
{
return $this->config->$key;
}
public function getSdkVersion()
{
return AlipayConstants::SDK_VERSION;
}
public function toUrlEncodedRequestBody($bizParams)
{
$sortedMap = $this->getSortedMap(null, $bizParams, null);
if (empty($sortedMap)) {
return null;
}
return $this->buildQueryString($sortedMap);
}
public function readAsJson($response, $method)
{
$responseBody = (string)$response->getBody();
$map = [];
$map[AlipayConstants::BODY_FIELD] = $responseBody;
$map[AlipayConstants::METHOD_FIELD] = $method;
return $map;
}
public function getRandomBoundary()
{
return date("Y-m-d H:i:s") . '';
}
public function toMultipartRequestBody($textParams, $fileParams, $boundary)
{
$this->textParams = $textParams;
if ($textParams != null && $this->optionalTextParams != null) {
$this->textParams = array_merge($textParams, $this->optionalTextParams);
} else if ($textParams == null) {
$this->textParams = $this->optionalTextParams;
}
if (count($fileParams) > 0) {
foreach ($fileParams as $key => $value) {
$fileField = new FileField();
$fileField->filename = $value;
$fileField->contentType = 'multipart/form-data;charset=utf-8;boundary=' . $boundary;
$fileField->content = new Stream(fopen($value, 'r'));
$this->textParams[$key] = $fileField;
}
}
$stream = FileForm::toFileForm($this->textParams, $boundary);
do {
$readLength = $stream->read(1024);
} while (0 != $readLength);
return $stream;
}
public function generatePage($method, $systemParams, $bizParams, $textParams, $sign)
{
if ($method == AlipayConstants::GET) {
$sortedMap = $this->getSortedMap($systemParams, $bizParams, $textParams);
$sortedMap[AlipayConstants::SIGN_FIELD] = $sign;
return $this->getGatewayServerUrl() . '?' . $this->buildQueryString($sortedMap);
} elseif ($method == AlipayConstants::POST) {
$sortedMap = $this->getSortedMap($systemParams, $this->bizParams, $this->textParams);
$sortedMap[AlipayConstants::SIGN_FIELD] = $sign;
$pageUtil = new PageUtil();
return $pageUtil->buildForm($this->getGatewayServerUrl(), $sortedMap);
} else {
throw new \Exception("不支持" . $method);
}
}
public function getMerchantCertSN()
{
return $this->config->merchantCertSN;
}
public function getAlipayCertSN(array $respMap)
{
if (!empty($this->config->merchantCertSN)) {
$body = json_decode($respMap[AlipayConstants::BODY_FIELD]);
$alipayCertSN = $body->alipay_cert_sn;
return $alipayCertSN;
}
}
public function getAlipayRootCertSN()
{
return $this->config->alipayRootCertSN;
}
public function isCertMode()
{
return $this->config->merchantCertSN;
}
public function extractAlipayPublicKey($alipayCertSN)
{
return $this->config->alipayPublicKey;
}
public function verify($respMap, $alipayPublicKey)
{
$resp = json_decode($respMap[AlipayConstants::BODY_FIELD], true);
$sign = $resp[AlipayConstants::SIGN_FIELD];
$signContentExtractor = new SignContentExtractor();
$content = $signContentExtractor->getSignSourceData($respMap[AlipayConstants::BODY_FIELD],
$respMap[AlipayConstants::METHOD_FIELD]);
$signer = new Signer();
return $signer->verify($content, $sign, $alipayPublicKey);
}
public function sign($systemParams, $bizParams, $textParams, $privateKey)
{
$sortedMap = $this->getSortedMap($systemParams, $bizParams, $textParams);
$data = $this->getSignContent($sortedMap);
$sign = new Signer();
return $sign->sign($data, $privateKey);
}
public function aesEncrypt($content, $encryptKey)
{
$aes = new AES();
return $aes->aesEncrypt($content, $encryptKey);
}
public function aesDecrypt($content, $encryptKey)
{
$aes = new AES();
return $aes->aesDecrypt($content, $encryptKey);
}
public function generateOrderString($systemParams, $bizParams, $textParams, $sign)
{
$sortedMap = $this->getSortedMap($systemParams, $bizParams, $textParams);
$sortedMap[AlipayConstants::SIGN_FIELD] = $sign;
return http_build_query($sortedMap);
}
public function sortMap($randomMap)
{
return $randomMap;
}
public function toRespModel($respMap)
{
$body = $respMap[AlipayConstants::BODY_FIELD];
$methodName = $respMap[AlipayConstants::METHOD_FIELD];
$responseNodeName = str_replace(".", "_", $methodName) . AlipayConstants::RESPONSE_SUFFIX;
$model = json_decode($body, true);
if (strpos($body, AlipayConstants::ERROR_RESPONSE)) {
$result = $model[AlipayConstants::ERROR_RESPONSE];
$result[AlipayConstants::BODY_FIELD] = $body;
} else {
$result = $model[$responseNodeName];
$result[AlipayConstants::BODY_FIELD] = $body;
}
return $result;
}
public function verifyParams($parameters, $publicKey)
{
$sign = new Signer();
return $sign->verifyParams($parameters, $publicKey);
}
public function concatStr($a, $b)
{
return $a . $b;
}
private function buildQueryString(array $sortedMap)
{
$requestUrl = null;
foreach ($sortedMap as $sysParamKey => $sysParamValue) {
$requestUrl .= "$sysParamKey=" . urlencode($this->characet($sysParamValue, AlipayConstants::DEFAULT_CHARSET)) . "&";
}
$requestUrl = substr($requestUrl, 0, -1);
return $requestUrl;
}
private function getSortedMap($systemParams, $bizParams, $textParams)
{
$this->textParams = $textParams;
$this->bizParams = $bizParams;
if ($textParams != null && $this->optionalTextParams != null) {
$this->textParams = array_merge($textParams, $this->optionalTextParams);
} else if ($textParams == null) {
$this->textParams = $this->optionalTextParams;
}
if ($bizParams != null && $this->optionalBizParams != null) {
$this->bizParams = array_merge($bizParams, $this->optionalBizParams);
} else if ($bizParams == null) {
$this->bizParams = $this->optionalBizParams;
}
$json = new JsonUtil();
if ($this->bizParams != null) {
$bizParams = $json->toJsonString($this->bizParams);
}
$sortedMap = $systemParams;
if (!empty($bizParams)) {
$sortedMap[AlipayConstants::BIZ_CONTENT_FIELD] = json_encode($bizParams, JSON_UNESCAPED_UNICODE);
}
if (!empty($this->textParams)) {
if (!empty($sortedMap)) {
$sortedMap = array_merge($sortedMap, $this->textParams);
} else {
$sortedMap = $this->textParams;
}
}
if ($this->getConfig(AlipayConstants::NOTIFY_URL_CONFIG_KEY) != null) {
$sortedMap[AlipayConstants::NOTIFY_URL_FIELD] = $this->getConfig(AlipayConstants::NOTIFY_URL_CONFIG_KEY);
}
return $sortedMap;
}
private function getSignContent($params)
{
ksort($params);
$stringToBeSigned = "";
$i = 0;
foreach ($params as $k => $v) {
if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
$v = $this->characet($v, AlipayConstants::DEFAULT_CHARSET);
if ($i == 0) {
$stringToBeSigned .= "$k" . "=" . "$v";
} else {
$stringToBeSigned .= "&" . "$k" . "=" . "$v";
}
$i++;
}
}
unset ($k, $v);
return $stringToBeSigned;
}
private function setNotifyUrl($params)
{
if ($this->config(AlipayConstants::NOTIFY_URL_CONFIG_KEY) != null && $params(AlipayConstants::NOTIFY_URL_CONFIG_KEY) == null) {
$params[AlipayConstants::NOTIFY_URL_CONFIG_KEY] = $this->config(AlipayConstants::NOTIFY_URL_CONFIG_KEY);
}
}
private function getGatewayServerUrl()
{
return $this->getConfig(AlipayConstants::PROTOCOL_CONFIG_KEY) . '://' . $this->getConfig(AlipayConstants::HOST_CONFIG_KEY) . '/gateway.do';
}
function checkEmpty($value)
{
if (!isset($value))
return true;
if ($value === null)
return true;
if (trim($value) === "")
return true;
return false;
}
function characet($data, $targetCharset)
{
if (!empty($data)) {
$fileType = AlipayConstants::DEFAULT_CHARSET;
if (strcasecmp($fileType, $targetCharset) != 0) {
$data = mb_convert_encoding($data, $targetCharset, $fileType);
}
}
return $data;
}
}