<?php
namespace Yurun\PaySDK\Weixin;
use Yurun\PaySDK\Base;
use Yurun\PaySDK\Lib\Encrypt\RSA;
use Yurun\PaySDK\Lib\ObjectToArray;
use Yurun\PaySDK\Lib\XML;
use Yurun\PaySDK\Weixin\Params\PublicParams;
use Yurun\PaySDK\Weixin\Report\Request;
class SDK extends Base
{
public $publicParams;
public $reportSDK;
public $signType;
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['_apiMethod'], $data['key'], $data['_method'], $data['_isSyncVerify'], $data['certPath'], $data['keyPath'], $data['apiCertPath'], $data['certSerialNumber'], $data['needSignType'], $data['allowReport'], $data['reportLevel'], $data['needNonceStr'], $data['signType'], $data['needAppID'], $data['rsaPublicCertFile'], $data['rsaPublicCertContent'], $data['needMchID'], $data['_contentType']);
if ($params->needAppID)
{
if (isset($params->mch_appid))
{
if ('' === $params->mch_appid)
{
$data['mch_appid'] = $this->publicParams->appID;
}
}
else
{
$data['appid'] = $this->publicParams->appID;
}
}
if (!$params->needMchID)
{
unset($data['mch_id']);
}
if (isset($params->mchid) && '' === $params->mchid)
{
$data['mchid'] = $this->publicParams->mch_id;
unset($data['mch_id']);
}
if (isset($params->partnerid) && '' === $params->partnerid)
{
$data['partnerid'] = $this->publicParams->mch_id;
unset($data['mch_id']);
}
if (true === $params->needNonceStr)
{
$data['nonce_str'] = md5(uniqid('', true));
}
elseif (\is_string($params->needNonceStr))
{
$data[$params->needNonceStr] = md5(uniqid('', true));
}
if (null === $params->signType)
{
$this->signType = $this->publicParams->sign_type;
}
else
{
$this->signType = $data['sign_type'] = $params->signType;
}
if (!$params->needSignType)
{
unset($data['sign_type']);
}
foreach ($data as $key => $value)
{
if (\is_object($value) && method_exists($value, 'toString'))
{
$data[$key] = $value->toString();
}
}
$data['sign'] = $this->sign($data);
$requestData = $this->parseDataToXML($data);
if (false === strpos($params->_apiMethod, '://'))
{
$url = $this->publicParams->apiDomain . $params->_apiMethod;
}
else
{
$url = $params->_apiMethod;
}
}
public function parseDataToXML($data)
{
return XML::toString($data);
}
public function sign($data)
{
$content = $this->parseSignData($data);
$signType = null === $this->signType ? $this->publicParams->sign_type : $this->signType;
switch ($signType)
{
case 'HMAC-SHA256':
return strtoupper(hash_hmac('sha256', $content, $this->publicParams->key));
case 'MD5':
return strtoupper(md5($content));
default:
throw new \Exception('未知的签名方式:' . $signType);
}
}
public function verifyCallback($data)
{
if (\is_string($data))
{
$data = XML::fromString($data);
}
if (!isset($data['sign']))
{
return false;
}
$content = $this->parseSignData($data);
switch ($this->publicParams->sign_type)
{
case 'HMAC-SHA256':
return strtoupper(hash_hmac('sha256', $content, $this->publicParams->key)) === $data['sign'];
case 'MD5':
return strtoupper(md5($content)) === $data['sign'];
default:
throw new \Exception('未知的签名方式:' . $this->publicParams->sign_type);
}
}
public function verifySync($params, $data, $response = null)
{
return $this->verifyCallback($data);
}
public function parseSignData($data)
{
unset($data['sign']);
ksort($data);
$data['key'] = $this->publicParams->key;
$content = '';
foreach ($data as $k => $v)
{
if ('' != $v && !\is_array($v))
{
$content .= $k . '=' . $v . '&';
}
}
return trim($content, '&');
}
public function execute($params, $format = 'XML')
{
if (null !== $this->publicParams->certPath)
{
$this->http->sslCert($this->publicParams->certPath);
}
if (null !== $this->publicParams->keyPath)
{
$this->http->sslKey($this->publicParams->keyPath);
}
parent::execute($params, $format);
if ($params->allowReport)
{
$this->report($params);
}
return $this->result;
}
public function report($params)
{
switch ($this->publicParams->reportLevel)
{
case PublicParams::REPORT_LEVEL_NONE:
return;
case PublicParams::REPORT_LEVEL_ALL:
break;
case PublicParams::REPORT_LEVEL_ERROR:
if ($this->checkResult())
{
return;
}
elseif (empty($this->result))
{
return;
}
break;
}
if (null === $this->reportSDK)
{
$this->reportSDK = new static($this->publicParams);
}
$request = new Request();
$request->interface_url = $this->url;
$request->execute_time_ = (int) ($this->response->totalTime() * 1000);
$request->return_code = isset($this->result['return_code']) ? $this->result['return_code'] : (empty($this->result) ? 'FAIL' : 'SUCCESS');
$request->return_msg = isset($this->result['return_msg']) ? $this->result['return_msg'] : null;
$request->result_code = isset($this->result['result_code']) ? $this->result['result_code'] : (empty($this->result) ? 'FAIL' : 'SUCCESS');
$request->err_code = isset($this->result['err_code']) ? $this->result['err_code'] : null;
$request->err_code_des = isset($this->result['err_code_des']) ? $this->result['err_code_des'] : null;
$request->user_ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
$request->time = date('YmdHis');
if (isset($params->device_info))
{
$request->device_info = $params->device_info;
}
if (isset($params->out_trade_no))
{
$request->out_trade_no = $params->out_trade_no;
}
}
protected function __checkResult($result)
{
return isset($result['return_code']) && 'SUCCESS' === $result['return_code'] && isset($result['result_code']) && 'SUCCESS' === $result['result_code'];
}
protected function __getError($result)
{
if (isset($result['result_code']) && 'SUCCESS' !== $result['result_code'])
{
return $result['err_code_des'];
}
if (isset($result['return_code']) && 'SUCCESS' !== $result['return_code'])
{
return $result['return_msg'];
}
return '';
}
protected function __getErrorCode($result)
{
if (isset($result['result_code']) && 'SUCCESS' !== $result['result_code'])
{
return $result['err_code'];
}
if (isset($result['return_code']) && 'SUCCESS' !== $result['return_code'])
{
return $result['return_code'];
}
return '';
}
public function saveRSAPublic($fileName, $result = null)
{
if (null === $result)
{
$result = $this->result;
}
file_put_contents($fileName, $result['pub_key']);
RSA::pkcs1To8($fileName, $fileName);
}
}