Skip to content

Commit

Permalink
Merge pull request #201 from mewebstudio/kuveytpos-non-secure-payment…
Browse files Browse the repository at this point in the history
…-integration

Kuveytpos non secure payment integration
  • Loading branch information
nuryagdym authored Apr 26, 2024
2 parents 6bf8f37 + 2e5a288 commit c8b470c
Show file tree
Hide file tree
Showing 17 changed files with 907 additions and 116 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ sistemlerinin kullanılabilmesidir.
| PosNetV1<br/>(JSON API) | Albaraka Türk | NonSecure<br/>3DSecure | İptal<br/>İade<br/>Durum sorgulama |
| PayFor | Finansbank<br/>Enpara | NonSecure<br/>3DSecure<br/>3DPay<br/>3DHost | İptal<br/>İade<br/>Durum sorgulama<br/>Sipariş Tarihçesini sorgulama<br/>Geçmiş İşlemleri sorgulama |
| InterPOS | Deniz bank | NonSecure<br/>3DSecure<br/>3DPay<br/>3DHost | İptal<br/>İade<br/>Durum sorgulama |
| Kuveyt POS TDV2.0.0 | Kuveyt Türk | 3DSecure | İptal<br/>İade<br/>Durum sorgulama<br/>(SOAP API) |
| Kuveyt POS TDV2.0.0 | Kuveyt Türk | NonSecure<br/>3DSecure | İptal<br/>İade<br/>Durum sorgulama<br/>(SOAP API) |
| VakifKatilimPos<br/>(test edilmesi gerekiyor) | Vakıf Katılım | NonSecure<br/>3DSecure<br/>3DHost | İptal<br/>İade<br/>Durum sorgulama<br/>Sipariş Tarihçesini sorgulama<br/>Geçmiş İşlemleri sorgulama |

### Ana başlıklar
Expand Down
2 changes: 1 addition & 1 deletion config/pos_production.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
'name' => 'kuveyt-pos',
'class' => Mews\Pos\Gateways\KuveytPos::class,
'gateway_endpoints' => [
'payment_api' => 'https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home/ThreeDModelProvisionGate',
'payment_api' => 'https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home',
'gateway_3d' => 'https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home/ThreeDModelPayGate',
'query_api' => 'https://boa.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl',
],
Expand Down
2 changes: 1 addition & 1 deletion config/pos_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
'name' => 'kuveyt-pos',
'class' => Mews\Pos\Gateways\KuveytPos::class,
'gateway_endpoints' => [
'payment_api' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelProvisionGate',
'payment_api' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home',
'gateway_3d' => 'https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelPayGate',
'query_api' => 'https://boatest.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc?wsdl',
],
Expand Down
2 changes: 1 addition & 1 deletion docs/PRE-AUTH-POST-EXAMPLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ try {
}
```
```html
<!-- $formData içeriği HTML forma render ediyoruz ve kullanıcıyı banka gateway'ine yönlendiriyoruy. -->
<!-- $formData içeriği HTML forma render ediyoruz ve kullanıcıyı banka gateway'ine yönlendiriyoruz. -->
<form method="<?= $formData['method']; ?>" action="<?= $formData['gateway']; ?>" class="redirect-form" role="form">
<?php foreach ($formData['inputs'] as $key => $value) : ?>
<input type="hidden" name="<?= $key; ?>" value="<?= $value; ?>">
Expand Down
2 changes: 1 addition & 1 deletion docs/THREED-PAYMENT-EXAMPLE.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ try {
}
```
```html
<!-- $formData içeriği HTML forma render ediyoruz ve kullanıcıyı banka gateway'ine yönlendiriyoruy. -->
<!-- $formData içeriği HTML forma render ediyoruz ve kullanıcıyı banka gateway'ine yönlendiriyoruz. -->
<form method="<?= $formData['method']; ?>" action="<?= $formData['gateway']; ?>" class="redirect-form" role="form">
<?php foreach ($formData['inputs'] as $key => $value) : ?>
<input type="hidden" name="<?= $key; ?>" value="<?= $value; ?>">
Expand Down
6 changes: 3 additions & 3 deletions examples/kuveytpos/regular/_config.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
$account = \Mews\Pos\Factory\AccountFactory::createKuveytPosAccount(
'kuveytpos',
'496',
'apiuser1',
'apitest',
'400235',
'Api1232',
'api123',
PosInterface::MODEL_3D_SECURE
);

$pos = getGateway($account, $eventDispatcher);

$templateTitle = 'Regular Payment';
$paymentModel = PosInterface::MODEL_3D_SECURE;
$paymentModel = PosInterface::MODEL_NON_SECURE;
3 changes: 2 additions & 1 deletion src/Crypt/KuveytPosCrypt.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
namespace Mews\Pos\Crypt;

use Mews\Pos\Entity\Account\AbstractPosAccount;
use Mews\Pos\Exceptions\NotImplementedException;

class KuveytPosCrypt extends AbstractCrypt
{
Expand Down Expand Up @@ -40,7 +41,7 @@ public function create3DHash(AbstractPosAccount $posAccount, array $requestData)
*/
public function check3DHash(AbstractPosAccount $posAccount, array $data): bool
{
return true;
throw new NotImplementedException();
}

/**
Expand Down
31 changes: 27 additions & 4 deletions src/DataMapper/RequestDataMapper/KuveytPosRequestDataMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function create3DPaymentRequestData(AbstractPosAccount $posAccount, array
'TransactionType' => $this->mapTxType($txType),
'InstallmentCount' => $responseData['VPosMessage']['InstallmentCount'],
'Amount' => $responseData['VPosMessage']['Amount'],
'DisplayAmount' => $this->formatAmount($responseData['VPosMessage']['Amount']),
'DisplayAmount' => $responseData['VPosMessage']['Amount'],
'CurrencyCode' => $responseData['VPosMessage']['CurrencyCode'],
'MerchantOrderId' => $responseData['VPosMessage']['MerchantOrderId'],
'TransactionSecurity' => $responseData['VPosMessage']['TransactionSecurity'],
Expand Down Expand Up @@ -161,11 +161,34 @@ public function createNonSecurePostAuthPaymentRequestData(AbstractPosAccount $po
}

/**
* @param KuveytPosAccount $posAccount
*
* {@inheritDoc}
*/
public function createNonSecurePaymentRequestData(AbstractPosAccount $posAccount, array $order, string $txType, CreditCardInterface $creditCard): array
{
throw new NotImplementedException();
$order = $this->preparePaymentOrder($order);

$requestData = $this->getRequestAccountData($posAccount) + [
'APIVersion' => self::API_VERSION,
'HashData' => '',
'TransactionType' => $this->mapTxType($txType),
'TransactionSecurity' => '1',
'MerchantOrderId' => (string) $order['id'],
'Amount' => $this->formatAmount($order['amount']),
'DisplayAmount' => $this->formatAmount($order['amount']),
'CurrencyCode' => $this->mapCurrency($order['currency']),
'InstallmentCount' => $this->mapInstallment($order['installment']),
'CardHolderName' => $creditCard->getHolderName(),
'CardNumber' => $creditCard->getNumber(),
'CardExpireDateYear' => $creditCard->getExpireYear(self::CREDIT_CARD_EXP_YEAR_FORMAT),
'CardExpireDateMonth' => $creditCard->getExpireMonth(self::CREDIT_CARD_EXP_MONTH_FORMAT),
'CardCVV2' => $creditCard->getCvv(),
];

$requestData['HashData'] = $this->crypt->createHash($posAccount, $requestData);

return $requestData;
}

/**
Expand Down Expand Up @@ -392,7 +415,7 @@ protected function mapInstallment(int $installment): string
*/
protected function preparePaymentOrder(array $order): array
{
return array_merge($order, [
return \array_merge($order, [
'installment' => $order['installment'] ?? 0,
'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY,
]);
Expand All @@ -403,7 +426,7 @@ protected function preparePaymentOrder(array $order): array
*/
protected function prepareStatusOrder(array $order): array
{
return array_merge($order, [
return \array_merge($order, [
'id' => $order['id'],
'currency' => $order['currency'] ?? PosInterface::CURRENCY_TRY,
'start_date' => $order['start_date'] ?? date_create('-360 day'),
Expand Down
20 changes: 15 additions & 5 deletions src/DataMapper/ResponseDataMapper/KuveytPosResponseDataMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class KuveytPosResponseDataMapper extends AbstractResponseDataMapper
*/
protected array $orderStatusMappings = [
1 => PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED,
5 => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED,
4 => PosInterface::PAYMENT_STATUS_FULLY_REFUNDED,
5 => PosInterface::PAYMENT_STATUS_PARTIALLY_REFUNDED,
6 => PosInterface::PAYMENT_STATUS_CANCELED,
];

Expand Down Expand Up @@ -123,15 +124,15 @@ public function map3DPaymentData(array $raw3DAuthResponseData, ?array $rawPaymen
*/
public function map3DPayResponseData(array $raw3DAuthResponseData, string $txType, array $order): array
{
return $this->map3DPaymentData($raw3DAuthResponseData, $raw3DAuthResponseData, $txType, $order);
throw new NotImplementedException();
}

/**
* {@inheritdoc}
*/
public function map3DHostResponseData(array $raw3DAuthResponseData, string $txType, array $order): array
{
return $this->map3DPayResponseData($raw3DAuthResponseData, $txType, $order);
throw new NotImplementedException();
}

/**
Expand Down Expand Up @@ -176,11 +177,20 @@ public function mapStatusResponse(array $rawResponseData): array
$defaultResponse['transaction_id'] = $orderContract['Stan'];
$defaultResponse['currency'] = $this->mapCurrency($orderContract['FEC']);
$defaultResponse['first_amount'] = (float) $orderContract['FirstAmount'];
$defaultResponse['capture_amount'] = null !== $orderContract['FirstAmount'] ? (float) $orderContract['FirstAmount'] : null;
$defaultResponse['capture'] = $defaultResponse['first_amount'] > 0 && $defaultResponse['first_amount'] === $defaultResponse['capture_amount'];
$defaultResponse['masked_number'] = $orderContract['CardNumber'];
$defaultResponse['transaction_time'] = new \DateTimeImmutable($orderContract['OrderDate']);
$defaultResponse['installment_count'] = $this->mapInstallment($orderContract['InstallmentCount']);
if (PosInterface::PAYMENT_STATUS_PAYMENT_COMPLETED === $defaultResponse['order_status']) {
$defaultResponse['capture_amount'] = null !== $orderContract['FirstAmount'] ? (float) $orderContract['FirstAmount'] : null;
$defaultResponse['capture'] = $defaultResponse['first_amount'] > 0 && $defaultResponse['first_amount'] === $defaultResponse['capture_amount'];
if ($defaultResponse['capture']) {
$defaultResponse['capture_time'] = new \DateTimeImmutable($orderContract['UpdateSystemDate']);
}
} elseif (PosInterface::PAYMENT_STATUS_CANCELED === $defaultResponse['order_status']) {
$defaultResponse['cancel_time'] = new \DateTimeImmutable($orderContract['UpdateSystemDate']);
} elseif (PosInterface::PAYMENT_STATUS_FULLY_REFUNDED === $defaultResponse['order_status']) {
$defaultResponse['refund_time'] = new \DateTimeImmutable($orderContract['UpdateSystemDate']);
}
}

return $defaultResponse;
Expand Down
77 changes: 58 additions & 19 deletions src/Gateways/KuveytPos.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use Mews\Pos\Entity\Account\KuveytPosAccount;
use Mews\Pos\Entity\Card\CreditCardInterface;
use Mews\Pos\Event\RequestDataPreparedEvent;
use Mews\Pos\Exceptions\HashMismatchException;
use Mews\Pos\Exceptions\UnsupportedPaymentModelException;
use Mews\Pos\Exceptions\UnsupportedTransactionTypeException;
use Mews\Pos\PosInterface;
Expand Down Expand Up @@ -46,6 +45,7 @@ class KuveytPos extends AbstractGateway
/** @inheritdoc */
protected static array $supportedTransactions = [
PosInterface::TX_TYPE_PAY_AUTH => [
PosInterface::MODEL_NON_SECURE,
PosInterface::MODEL_3D_SECURE,
],
PosInterface::TX_TYPE_PAY_PRE_AUTH => false,
Expand All @@ -63,6 +63,29 @@ public function getAccount(): AbstractPosAccount
return $this->account;
}

/**
* @inheritDoc
*/
public function getApiURL(string $txType = null, string $paymentModel = null, ?string $orderTxType = null): string
{
if (\in_array(
$txType,
[
PosInterface::TX_TYPE_REFUND,
PosInterface::TX_TYPE_STATUS,
PosInterface::TX_TYPE_CANCEL,
],
true
)) {
return $this->getQueryAPIUrl();
}
if (null !== $txType && null !== $paymentModel) {
return parent::getApiURL().'/'.$this->getRequestURIByTransactionType($txType, $paymentModel);
}

return parent::getApiURL();
}

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -108,14 +131,6 @@ public function get3DFormData(array $order, string $paymentModel, string $txType
return $this->getCommon3DFormData($this->account, $order, $paymentModel, $txType, $gatewayUrl, $creditCard);
}

/**
* @inheritDoc
*/
public function makeRegularPayment(array $order, CreditCardInterface $creditCard, string $txType): PosInterface
{
throw new UnsupportedPaymentModelException();
}

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -143,10 +158,6 @@ public function make3DPayment(Request $request, array $order, string $txType, Cr
return $this;
}

if (!$this->requestDataMapper->getCrypt()->check3DHash($this->account, $gatewayResponse)) {
throw new HashMismatchException();
}

$this->logger->debug('finishing payment');

$requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $gatewayResponse);
Expand All @@ -168,7 +179,7 @@ public function make3DPayment(Request $request, array $order, string $txType, Cr
$contents,
$txType,
PosInterface::MODEL_3D_SECURE,
$this->getApiURL()
$this->getApiURL($txType, PosInterface::MODEL_3D_SECURE)
);

$this->response = $this->responseDataMapper->map3DPaymentData($gatewayResponse, $bankResponse, $txType, $order);
Expand All @@ -190,7 +201,7 @@ protected function send($contents, string $txType, string $paymentModel, string
throw new InvalidArgumentException(\sprintf('Invalid data type provided for %s transaction!', $txType));
}

return $this->data = $this->sendSoapRequest($contents, $txType);
return $this->data = $this->sendSoapRequest($contents, $txType, $url);
}

$this->logger->debug('sending request', ['url' => $url]);
Expand All @@ -209,17 +220,17 @@ protected function send($contents, string $txType, string $paymentModel, string
/**
* @phpstan-param PosInterface::TX_TYPE_STATUS|PosInterface::TX_TYPE_REFUND|PosInterface::TX_TYPE_CANCEL $txType
*
* @param array<string, mixed> $contents
* @param string $txType
* @param array<string, mixed> $contents
* @param string $txType
* @param string $url
*
* @return array<string, mixed>
*
* @throws SoapFault
* @throws Throwable
*/
protected function sendSoapRequest(array $contents, string $txType): array
private function sendSoapRequest(array $contents, string $txType, string $url): array
{
$url = $this->getQueryAPIUrl();
$this->logger->debug('sending soap request', [
'txType' => $txType,
'url' => $url,
Expand Down Expand Up @@ -313,4 +324,32 @@ private function getCommon3DFormData(KuveytPosAccount $kuveytPosAccount, array $

return $this->requestDataMapper->create3DFormData($this->account, $decodedResponse['form_inputs'], $paymentModel, $txType, $decodedResponse['gateway'], $creditCard);
}

/**
* @phpstan-param PosInterface::TX_TYPE_* $txType
* @phpstan-param PosInterface::MODEL_* $paymentModel
*
* @return string
*
* @throws UnsupportedTransactionTypeException
*/
private function getRequestURIByTransactionType(string $txType, string $paymentModel): string
{
$arr = [
PosInterface::TX_TYPE_PAY_AUTH => [
PosInterface::MODEL_NON_SECURE => 'Non3DPayGate',
PosInterface::MODEL_3D_SECURE => 'ThreeDModelProvisionGate',
],
];

if (!isset($arr[$txType])) {
throw new UnsupportedTransactionTypeException();
}

if (!isset($arr[$txType][$paymentModel])) {
throw new UnsupportedTransactionTypeException();
}

return $arr[$txType][$paymentModel];
}
}
5 changes: 0 additions & 5 deletions src/Gateways/VakifKatilimPos.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Mews\Pos\Entity\Account\KuveytPosAccount;
use Mews\Pos\Entity\Card\CreditCardInterface;
use Mews\Pos\Event\RequestDataPreparedEvent;
use Mews\Pos\Exceptions\HashMismatchException;
use Mews\Pos\Exceptions\UnsupportedPaymentModelException;
use Mews\Pos\Exceptions\UnsupportedTransactionTypeException;
use Mews\Pos\PosInterface;
Expand Down Expand Up @@ -122,10 +121,6 @@ public function make3DPayment(Request $request, array $order, string $txType, Cr
return $this;
}

if (!$this->requestDataMapper->getCrypt()->check3DHash($this->account, $gatewayResponse)) {
throw new HashMismatchException();
}

$this->logger->debug('finishing payment');

$requestData = $this->requestDataMapper->create3DPaymentRequestData($this->account, $order, $txType, $gatewayResponse);
Expand Down
Loading

0 comments on commit c8b470c

Please sign in to comment.