diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/composer.json b/composer.json old mode 100644 new mode 100755 index 0da34e1..6b1af0c --- a/composer.json +++ b/composer.json @@ -13,8 +13,8 @@ } ], "require": { - "php": ">=7.2", - "guzzlehttp/guzzle": "^6.2" + "php": ">=7.4", + "guzzlehttp/guzzle": "^6.2|^7" }, "require-dev": { "phpunit/phpunit": "^6.3" diff --git a/src/Callback.php b/src/Callback.php new file mode 100755 index 0000000..4ceaca6 --- /dev/null +++ b/src/Callback.php @@ -0,0 +1,47 @@ +success = $success; + $this->failed = $failed; + $this->callback = $callback; + } + + /** + * @return string|null + */ + public function getSuccess(): ?string + { + return $this->success; + } + + /** + * @return string|null + */ + public function getFailed(): ?string + { + return $this->failed; + } + + /** + * @return string|null + */ + public function getCallback(): ?string + { + return $this->callback; + } +} diff --git a/src/Customer.php b/src/Customer.php old mode 100644 new mode 100755 index c621535..26ec2d0 --- a/src/Customer.php +++ b/src/Customer.php @@ -4,56 +4,55 @@ class Customer { + private string $firstName; + private string $name; + private ?string $email; + private ?string $phone; + /** - * @var string - */ - private $customerName; - /** - * @var string - */ - private $customerEmail; - /** - * @var string + * Customer constructor. + * @param string $firstName + * @param string $name + * @param string|null $email + * @param string|null $phone */ - private $customerPhone; + public function __construct(string $name, string $firstName, ?string $email = null, ?string $phone = null) + { + $this->firstName = $firstName; + $this->name = $name; + $this->email = $email; + $this->phone = $phone; + } /** - * Customer constructor. - * @param string $customerName - * @param string|null $customerEmail - * @param string|null $customerPhone + * @return string */ - public function __construct( - string $customerName, - ?string $customerEmail = null, - ?string $customerPhone = null - ) { - $this->customerName = $customerName; - $this->customerEmail = $customerEmail; - $this->customerPhone = $customerPhone; + public function getFirstName(): string + { + return $this->firstName; } /** * @return string */ - public function getCustomerName(): string + public function getName(): string { - return $this->customerName; + return $this->name; } /** * @return string */ - public function getCustomerEmail(): ?string + public function getEmail(): ?string { - return $this->customerEmail; + return $this->email; } /** * @return string */ - public function getCustomerPhone(): ?string + public function getPhone(): ?string { - return $this->customerPhone; + return $this->phone; } -} \ No newline at end of file +} diff --git a/src/IpsPayment.php b/src/IpsPayment.php old mode 100644 new mode 100755 index adfc9cf..2921fd1 --- a/src/IpsPayment.php +++ b/src/IpsPayment.php @@ -4,32 +4,89 @@ namespace SchGroup\IpsPayment; -use GuzzleHttp\ClientInterface; +use Exception; +use JsonException; class IpsPayment { + private const HEADERS = ['Content-Type: application/x-www-form-urlencoded']; + /** - * @var ClientInterface + * @param Transaction $transaction + * @return string + * @throws JsonException + * @throws Exception */ - private $client; + public function buildLink(Transaction $transaction): string + { + $requestBody = $this->prepareParams($transaction); + $requestLink = $transaction->getShopSettings()->getTransitionPath(); + $response = $this->sendRequest($requestLink, $requestBody); + + $this->prepareResponse($response); + + return $response['DirectLinkIs']; + } /** - * IpsPayment constructor. - * @param ClientInterface $client + * @param Transaction $transaction + * @return array */ - public function __construct(ClientInterface $client) + private function prepareParams(Transaction $transaction): array { - $this->client = $client; + $paramsToString = implode('!', array_values($transaction->toArray())); + $paramsToString .= '!' . $transaction->getShopSettings()->getSecretKey(); + $paramsToString .= '|' . $transaction->getShopSettings()->getSecretKey(); + + return array_merge($transaction->toArray(), [ + 'SHA' => hash('sha512', base64_encode($paramsToString)) + ]); } + /** + * @param string $link + * @return array + * ```php + * [ + * 'Code' => '200', + * 'Method' => 'GET", + * 'Url_To_Redirect_Customer' => '', + * 'SACS' => '', + * 'DirectLinkIs' => '', + * ] + * [ + * 'ErrorCode' => '', + * 'ErrorDescription' => '', + * ] + * ``` + * @throws Exception + * @throws JsonException + */ + private function sendRequest(string $link, array $body): array + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $link . '/'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($body)); + curl_setopt($ch, CURLOPT_HTTPHEADER, self::HEADERS); + $result = curl_exec($ch); + + if (curl_errno($ch)) { + throw new Exception('Curl request error: ' . $ch); + } + + return json_decode($result, true, 512, JSON_THROW_ON_ERROR); + } /** - * @param Transaction $transaction - * @return string + * @param array $response + * @throws Exception */ - public function buildLink(Transaction $transaction): string + private function prepareResponse(array $response): void { - return $transaction->getShopSettings()->getApiHost() .'?'. http_build_query($transaction->toArray()); + if (!isset($response['Code'])) { + throw new Exception('ips request error: ' . $response['ErrorDescription']); + } } - -} \ No newline at end of file +} diff --git a/src/Order.php b/src/Order.php old mode 100644 new mode 100755 index d1d9fcf..4ac43e1 --- a/src/Order.php +++ b/src/Order.php @@ -4,22 +4,10 @@ class Order { - /** - * @var float - */ - private $amount; - /** - * @var string - */ - private $subscribePeriod; - /** - * @var string - */ - private $refOrder; - /** - * @var string - */ - private $subscribe; + private float $amount; + private ?string $subscribePeriod; + private string $refOrder; + private ?string $subscribe; /** * Order constructor. @@ -33,8 +21,7 @@ public function __construct( float $amount, ?string $subscribe = null, ?string $subscribePeriod = null - ) - { + ) { $this->refOrder = $refOrder; $this->subscribe = $subscribe; $this->subscribePeriod = $subscribePeriod; @@ -72,6 +59,4 @@ public function getSubscribe(): ?string { return $this->subscribe; } - - -} \ No newline at end of file +} diff --git a/src/ShopSettings.php b/src/ShopSettings.php old mode 100644 new mode 100755 index d522914..e17fbe4 --- a/src/ShopSettings.php +++ b/src/ShopSettings.php @@ -4,46 +4,26 @@ class ShopSettings { + private const TRANSACTION_PATH = 'init_transactions'; - /** - * @var string - */ - private $Integrated; - - /** - * @var string - */ - private $lang; - /** - * @var string - */ - private $merchantKey; - /** - * @var string - */ - private $apiHost; + private ?string $lang; + private string $merchantKey; + private string $apiHost; + private string $secretKey; /** * ShopSettings constructor. - * @param string $merchantKey - * @param string $apiHost - * @param string|null $Integrated + * @param string $merchantKey + * @param string $apiHost + * @param string $secretKey * @param string|null $lang */ - public function __construct(string $merchantKey, string $apiHost, string $Integrated = "NO", string $lang = null) + public function __construct(string $merchantKey, string $apiHost, string $secretKey, string $lang = null) { $this->merchantKey = $merchantKey; - $this->Integrated = $Integrated; $this->lang = $lang; $this->apiHost = $apiHost; - } - - /** - * @return string - */ - public function getIntegrated(): string - { - return $this->Integrated; + $this->secretKey = $secretKey; } /** @@ -69,4 +49,20 @@ public function getApiHost(): string { return $this->apiHost; } -} \ No newline at end of file + + /** + * @return string + */ + public function getTransitionPath(): string + { + return $this->apiHost . '/' . self::TRANSACTION_PATH; + } + + /** + * @return string + */ + public function getSecretKey(): string + { + return $this->secretKey; + } +} diff --git a/src/Transaction.php b/src/Transaction.php old mode 100644 new mode 100755 index 607dc5a..3b93378 --- a/src/Transaction.php +++ b/src/Transaction.php @@ -4,34 +4,28 @@ class Transaction { - /** - * @var Customer - */ - private $customer; - - /** - * @var Order - */ - private $order; - /** - * @var ShopSettings - */ - private $shopSettings; + private Customer $customer; + private Order $order; + private ShopSettings $shopSettings; + private Callback $callback; /** * Transaction constructor. * @param Order $order * @param Customer $customer * @param ShopSettings $shopSettings + * @param Callback $callback */ public function __construct( Order $order, Customer $customer, - ShopSettings $shopSettings + ShopSettings $shopSettings, + Callback $callback ) { $this->customer = $customer; $this->order = $order; $this->shopSettings = $shopSettings; + $this->callback = $callback; } /** @@ -40,17 +34,19 @@ public function __construct( public function toArray(): array { $params = [ - "MerchantKey"=> $this->shopSettings->getMerchantKey(), - "RefOrder" => $this->order->getRefOrder(), - "amount" => $this->order->getAmount(), - "Customer_Name" => $this->customer->getCustomerName(), - "Customer_Email" => $this->customer->getCustomerEmail(), - "Customer_Phone" => $this->customer->getCustomerPhone(), - "Integrated" => $this->shopSettings->getIntegrated(), + 'MerchantKey' => $this->shopSettings->getMerchantKey(), + 'amount' => (string)$this->order->getAmount(), + 'RefOrder' => $this->order->getRefOrder(), ]; - if(!empty($this->shopSettings->getLang())) { - $params["lang"] = $this->shopSettings->getLang(); - } + + $this->customer->getName() && $params['Customer_Name'] = $this->customer->getName(); + $this->customer->getFirstName() && $params['Customer_FirstName'] = $this->customer->getFirstName(); + $this->customer->getEmail() && $params['Customer_Email'] = (string)$this->customer->getEmail(); + $this->customer->getPhone() && $params['Customer_Phone'] = (string)$this->customer->getPhone(); + $this->shopSettings->getLang() && $params['lang'] = (string)$this->shopSettings->getLang(); + $this->callback->getCallback() && $params['urlIPN'] = (string)$this->callback->getCallback(); + $this->callback->getSuccess() && $params['urlOK'] = (string)$this->callback->getSuccess(); + $this->callback->getFailed() && $params['urlKO'] = (string)$this->callback->getFailed(); return $params; } @@ -78,4 +74,4 @@ public function getShopSettings(): ShopSettings { return $this->shopSettings; } -} \ No newline at end of file +}