Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
recca0120 committed Nov 12, 2023
1 parent 497bb5c commit 49e04b1
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 78 deletions.
77 changes: 50 additions & 27 deletions src/Encryptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,47 +33,37 @@ public function decrypt(string $plainText): string

public function tradeSha($data)
{
if (is_array($data)) {
ksort($data);
$plainText = http_build_query($data);
} else {
$plainText = $data;
}

return strtoupper(hash(
"sha256",
implode('&', ['HashKey='.$this->hashKey, $plainText, 'HashIV='.$this->hashIv])
));
return $this->makeHash([
'HashKey='.$this->hashKey,
$this->toPlainText($data),
'HashIV='.$this->hashIv,
]);
}

public function checkValue($data)
{
if (is_array($data)) {
ksort($data);
$plainText = http_build_query($data);
} else {
$plainText = $data;
$data = self::only($data, ['MerchantID', 'Amt', 'MerchantOrderNo']);
}

return strtoupper(hash(
"sha256",
implode('&', ['IV='.$this->hashIv, $plainText, 'Key='.$this->hashKey])
));
return $this->makeHash([
'IV='.$this->hashIv,
$this->toPlainText($data),
'Key='.$this->hashKey,
]);
}

public function checkCode($data)
{
if (is_array($data)) {
ksort($data);
$plainText = http_build_query($data);
} else {
$plainText = $data;
$data = self::only($data, ['MerchantID', 'Amt', 'MerchantOrderNo', 'TradeNo']);
}

return strtoupper(hash(
"sha256",
implode('&', ['HashIV='.$this->hashIv, $plainText, 'HashKey='.$this->hashKey])
));
return $this->makeHash([
'HashIV='.$this->hashIv,
$this->toPlainText($data),
'HashKey='.$this->hashKey,
]);
}

private function stripPadding($value)
Expand All @@ -89,4 +79,37 @@ private function paddingIsValid($pad, $value)

return substr($value, $beforePad) === str_repeat(substr($value, -1), $pad);
}

/**
* @param string|array $data
* @return string
*/
private function toPlainText($data)
{
if (! is_array($data)) {
$plainText = $data;
} else {
ksort($data);
$plainText = http_build_query($data);
}

return $plainText;
}

private function makeHash(array $data)
{
return strtoupper(hash("sha256", implode('&', $data)));
}

private static function only(array $array, array $keys = [])
{
$result = [];
foreach ($keys as $key) {
if (array_key_exists($key, $array)) {
$result[$key] = $array[$key];
}
}

return $result;
}
}
10 changes: 2 additions & 8 deletions src/Message/AcceptNotificationRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,13 @@

namespace Omnipay\NewebPay\Message;

use Omnipay\Common\Exception\InvalidResponseException;
use Omnipay\Common\Message\NotificationInterface;

class AcceptNotificationRequest extends CompletePurchaseRequest implements NotificationInterface
{
/**
* @param array $data
* @return AcceptNotificationResponse
* @throws InvalidResponseException
*/
public function sendData($data)
{
return $this->response = new AcceptNotificationResponse($this, $this->decrypt($data));
return $this->response = new AcceptNotificationResponse($this, $data);
}

public function getTransactionId()
Expand All @@ -38,7 +32,7 @@ public function getMessage()
}

/**
* @return CompletePurchaseResponse
* @return AcceptNotificationResponse
*/
private function getNotificationResponse()
{
Expand Down
32 changes: 10 additions & 22 deletions src/Message/CompletePurchaseRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,29 @@
namespace Omnipay\NewebPay\Message;

use Omnipay\Common\Exception\InvalidResponseException;
use Omnipay\NewebPay\Encryptor;
use Omnipay\NewebPay\Traits\HasDefaults;

class CompletePurchaseRequest extends AbstractRequest
{
use HasDefaults;

public function getData()
{
return $this->httpRequest->request->all();
}

/**
* @throws InvalidResponseException
*/
public function sendData($data)
{
return $this->response = new CompletePurchaseResponse($this, $this->decrypt($data));
}

/**
* @throws InvalidResponseException
*/
protected function decrypt($data)
public function getData()
{
$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());
$tradeSha = $encryptor->tradeSha($data['TradeInfo']);

$data = $this->httpRequest->request->all();
$tradeSha = $this->tradeSha($data['TradeInfo']);
if (! hash_equals($tradeSha, $data['TradeSha'])) {
throw new InvalidResponseException();
throw new InvalidResponseException('Incorrect TradeSha');
}

$data['Result'] = [];
parse_str($encryptor->decrypt($data['TradeInfo']), $data['Result']);
$data['Result'] = $this->decrypt($data['TradeInfo']);

return $data;
}

public function sendData($data)
{
return $this->response = new CompletePurchaseResponse($this, $data);
}
}
23 changes: 6 additions & 17 deletions src/Message/FetchTransactionRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Omnipay\Common\Exception\InvalidRequestException;
use Omnipay\Common\Exception\InvalidResponseException;
use Omnipay\NewebPay\Encryptor;
use Omnipay\NewebPay\Traits\HasDefaults;

class FetchTransactionRequest extends AbstractRequest
Expand Down Expand Up @@ -48,24 +47,21 @@ public function getGateway()
*/
public function getData()
{
$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());

return array_filter([
$data = array_filter([
'MerchantID' => $this->getMerchantID(),
'Version' => $this->getVersion() ?: '1.3',
'RespondType' => $this->getRespondType(),
'CheckValue' => $encryptor->checkValue([
'Amt' => (int) $this->getAmount(),
'MerchantID' => $this->getMerchantID(),
'MerchantOrderNo' => $this->getTransactionId(),
]),
'TimeStamp' => $this->getTimeStamp(),
'MerchantOrderNo' => $this->getTransactionId(),
'Amt' => (int) $this->getAmount(),
'Gateway' => $this->getGateway(),
], static function ($value) {
return $value !== null && $value !== '';
});

$data['CheckValue'] = $this->checkValue($data);

return $data;
}

/**
Expand All @@ -78,14 +74,7 @@ public function sendData($data)
], http_build_query($data));
$result = json_decode((string) $response->getBody(), true);

$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());

if (! hash_equals($result['Result']['CheckCode'], $encryptor->checkCode([
'MerchantID' => $result['Result']['MerchantID'],
'Amt' => $result['Result']['Amt'],
'MerchantOrderNo' => $result['Result']['MerchantOrderNo'],
'TradeNo' => $result['Result']['TradeNo'],
]))) {
if (! hash_equals($result['Result']['CheckCode'], $this->checkCode($result['Result']))) {
throw new InvalidResponseException('Incorrect CheckCode');
}

Expand Down
6 changes: 2 additions & 4 deletions src/Message/PurchaseResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Omnipay\NewebPay\Message;

use Omnipay\Common\Message\RedirectResponseInterface;
use Omnipay\NewebPay\Encryptor;

class PurchaseResponse extends AbstractResponse implements RedirectResponseInterface
{
Expand All @@ -29,13 +28,12 @@ public function getRedirectMethod()

public function getRedirectData()
{
$encryptor = new Encryptor($this->request->getHashKey(), $this->request->getHashIv());
$tradeInfo = $encryptor->encrypt($this->data);
$tradeInfo = $this->request->encrypt($this->data);

return [
'MerchantID' => $this->data['MerchantID'],
'TradeInfo' => $tradeInfo,
'TradeSha' => $encryptor->tradeSha($tradeInfo),
'TradeSha' => $this->request->tradeSha($tradeInfo),
'Version' => $this->data['Version'],
];
}
Expand Down
39 changes: 39 additions & 0 deletions src/Traits/HasDefaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Omnipay\NewebPay\Traits;

use Omnipay\Common\Exception\InvalidRequestException;
use Omnipay\NewebPay\Encryptor;

trait HasDefaults
{
Expand Down Expand Up @@ -156,4 +157,42 @@ public function getAmt()
{
return (int) $this->getAmount();
}

public function encrypt(array $data)
{
$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());

return $encryptor->encrypt($data);
}

public function decrypt(string $plainText)
{
$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());

$data = [];
parse_str($encryptor->decrypt($plainText), $data);

return $data;
}

public function tradeSha($plainText)
{
$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());

return $encryptor->tradeSha($plainText);
}

public function checkValue($data)
{
$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());

return $encryptor->checkValue($data);
}

public function checkCode($data)
{
$encryptor = new Encryptor($this->getHashKey(), $this->getHashIv());

return $encryptor->checkCode($data);
}
}
25 changes: 25 additions & 0 deletions tests/Message/CompletePurchaseRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,31 @@ public function testGetData(): array
'Version' => '2.0',
'TradeInfo' => 'ee11d1501e6dc8433c75988258f2343d11f4d0a423be672e8e02aaf373c53c2363aeffdb4992579693277359b3e449ebe644d2075fdfbc10150b1c40e7d24cb215febefdb85b16a5cde449f6b06c58a5510d31e8d34c95284d459ae4b52afc1509c2800976a5c0b99ef24cfd28a2dfc8004215a0c98a1d3c77707773c2f2132f9a9a4ce3475cb888c2ad372485971876f8e2fec0589927544c3463d30c785c2d3bd947c06c8c33cf43e131f57939e1f7e3b3d8c3f08a84f34ef1a67a08efe177f1e663ecc6bedc7f82640a1ced807b548633cfa72d060864271ec79854ee2f5a170aa902000e7c61d1269165de330fce7d10663d1668c711571776365bfdcd7ddc915dcb90d31a9f27af9b79a443ca8302e508b0dbaac817d44cfc44247ae613075dde4ac960f1bdff4173b915e4344bc4567bd32e86be7d796e6d9b9cf20476e4996e98ccc315f1ed03a34139f936797d971f2a3f90bc18f8a155a290bcbcf04f4277171c305bf554f5cba243154b30082748a81f2e5aa432ef9950cc9668cd4330ef7c37537a6dcb5e6ef01b4eca9705e4b097cf6913ee96e81d0389e5f775',
'TradeSha' => 'C80876AEBAC0036268C0E240E5BFF69C0470DE9606EEE083C5C8DD64FDB3347A',
'Result' => [
'Status' => 'SUCCESS',
'Message' => '授權成功',
'MerchantID' => 'MS127874575',
'Amt' => '30',
'TradeNo' => '23092714215835071',
'MerchantOrderNo' => 'Vanespl_ec_1695795668',
'RespondType' => 'String',
'IP' => '123.51.237.115',
'EscrowBank' => 'HNCB',
'PaymentType' => 'CREDIT',
'RespondCode' => '00',
'Auth' => '115468',
'Card6No' => '400022',
'Card4No' => '1111',
'Exp' => '2609',
'AuthBank' => 'KGI',
'TokenUseStatus' => '0',
'InstFirst' => '0',
'InstEach' => '0',
'Inst' => '0',
'ECI' => '',
'PayTime' => '2023-09-27 14:21:59',
'PaymentMethod' => 'CREDIT',
],
], $data);

return [$request->send(), $data];
Expand Down

0 comments on commit 49e04b1

Please sign in to comment.