Skip to content

Commit

Permalink
Implement support for refunds
Browse files Browse the repository at this point in the history
  • Loading branch information
dnna committed Oct 19, 2018
1 parent b10e47f commit 2155408
Show file tree
Hide file tree
Showing 10 changed files with 248 additions and 34 deletions.
3 changes: 3 additions & 0 deletions Action/Api/BaseApiAwareAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Payum\Core\GatewayAwareTrait;
use Dnna\Payum\AlphaBank\Api;

/**
* @property Api $api
*/
abstract class BaseApiAwareAction implements ActionInterface, GatewayAwareInterface, ApiAwareInterface
{
use GatewayAwareTrait;
Expand Down
8 changes: 4 additions & 4 deletions Action/Api/CreateChargeAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public function execute($request): void
$model['retries'] = 1;
}

$model['hashedOrderid'] = md5($model['orderid'] . 'H' . $request->getToken()->getHash() . $retries);

$mappedModel = new ArrayObject();
if (isset($model['mid'])) {
$mappedModel['mid'] = $model['mid'];
Expand Down Expand Up @@ -127,8 +129,8 @@ public function execute($request): void
unset($mappedModel['custom5']);
}


$mappedModel['orderid'] = md5($mappedModel['orderid'] . 'H' . $request->getToken()->getHash() . $retries);
$mappedModel['orderid'] = $model['hashedOrderid'];
unset($mappedModel['hashedOrderid']);

if (isset($mappedModel['sharedSecretKey'])) {
unset($mappedModel['sharedSecretKey']);
Expand All @@ -137,8 +139,6 @@ public function execute($request): void

$mappedModel['digest'] = $digestCalculator->calculateDigest($mappedModel);

$model['hashedOrderid'] = $mappedModel['orderid'];

$this->gateway->execute(
$renderTemplate = new RenderTemplate(
$this->templateName,
Expand Down
114 changes: 114 additions & 0 deletions Action/Api/RequestRefundAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

namespace Dnna\Payum\AlphaBank\Action\Api;

use Dnna\Payum\AlphaBank\Request\Api\CreateCharge;
use Dnna\Payum\AlphaBank\Request\Api\RequestRefund;
use Dnna\Payum\AlphaBank\Util\DigestCalculator;
use Dnna\Payum\AlphaBank\Util\XMLHandler;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Security\SensitiveValue;
use Payum\Core\Exception\RequestNotSupportedException;

class RequestRefundAction extends BaseApiAwareAction
{
protected $mid;
protected $sharedSecretKey;

public function __construct($mid, $sharedSecretKey)
{
$this->mid = $mid;
$this->sharedSecretKey = $sharedSecretKey;
parent::__construct();
}

public function execute($request): void
{
/** @var $request CreateCharge */
RequestNotSupportedException::assertSupports($this, $request);

$model = ArrayObject::ensureArrayObject($request->getModel());

if ($model['status'] === 'REFUNDED') {
return;
}
if ($model['status'] !== 'CAPTURED') {
throw new \DomainException('Cannot refund a non-captured transaction');
}

if (isset($model['mid'])) {
$mid = $model['mid'];
} elseif ($this->mid != null) {
$mid = $this->mid;
} else {
throw new \LogicException('mid must be specified in the payment model or the factory');
}

if (isset($model['sharedSecretKey'])) {
if ($model['sharedSecretKey'] instanceof SensitiveValue) {
$digestCalculator = new DigestCalculator($model['sharedSecretKey']->peek());
} else {
$digestCalculator = new DigestCalculator($model['sharedSecretKey']);
}
} elseif ($this->sharedSecretKey != null) {
$digestCalculator = new DigestCalculator($this->sharedSecretKey);
} else {
throw new \LogicException('sharedSecretKey must be specified in the payment model or the factory');
}

$requests = [
'RefundRequest' => 'RefundResponse',
'CancelRequest' => 'CancelResponse',
];
foreach ($requests as $curRequestType => $curResponseType) {
$data = [
'VPOS' => [
'_attributes' => ['xmlns' => 'http://www.modirum.com/schemas'],
'Message' => [
'_attributes' => [
'xmlns' => 'http://www.modirum.com/schemas',
'messageId' => uniqid('refund', true),
'version' => '1.0',
],
$curRequestType => [
'Authentication' => [
'Mid' => $mid,
],
'OrderInfo' => [
'OrderId' => $model['hashedOrderid'],
'OrderAmount' => $model['orderAmount'],
'Currency' => $model['currency'],
],
],
],
],
];

$xmlHandler = new XMLHandler();
$messageXml = $xmlHandler->arrayToXml($data)->Message->asXML();
$digest = $digestCalculator->calculateDigestForString($messageXml);

$data['VPOS']['Digest'] = $digest;

$response = $this->api->sendXMLRequest($xmlHandler->arrayToXml($data)->asXML());
$responseArray = json_decode(json_encode((array)simplexml_load_string($response->getBody())), true);
if (isset($responseArray['Message'][$curResponseType]) &&
$responseArray['Message'][$curResponseType]['TxId'] != 0 &&
$responseArray['Message'][$curResponseType]['Status'] !== 'ERROR'
) {
$model['status'] = 'REFUNDED';
}
}

if ($model['status'] !== 'REFUNDED') {
throw new \DomainException('Refund did not complete');
}
}

public function supports($request): bool
{
return
$request instanceof RequestRefund &&
$request->getModel() instanceof \ArrayAccess;
}
}
21 changes: 15 additions & 6 deletions Action/RefundAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use Payum\Core\Request\Refund;
use Payum\Core\Exception\RequestNotSupportedException;

use Dnna\Payum\AlphaBank\Request\Api\CreateCharge;
use Dnna\Payum\AlphaBank\Request\Api\RequestRefund;

class RefundAction implements ActionInterface, GatewayAwareInterface
{
Expand All @@ -17,21 +17,30 @@ class RefundAction implements ActionInterface, GatewayAwareInterface
/**
* {@inheritDoc}
*
* @param Capture $request
* @param Refund $request
*/
public function execute($request)
public function execute($request): void
{
RequestNotSupportedException::assertSupports($this, $request);

//$model = ArrayObject::ensureArrayObject($request->getModel());
$model = ArrayObject::ensureArrayObject($request->getModel());

throw new \LogicException('Not supported');
if ($model['status'] === 'REFUNDED') {
return;
}
if ($model['status'] !== 'CAPTURED') {
throw new \DomainException('Cannot refund a non-captured transaction');
}

$requestRefund = new RequestRefund($request->getToken());
$requestRefund->setModel($model);
$this->gateway->execute($requestRefund);
}

/**
* {@inheritDoc}
*/
public function supports($request)
public function supports($request): bool
{
return
$request instanceof Refund &&
Expand Down
21 changes: 14 additions & 7 deletions Action/StatusAction.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php

namespace Dnna\Payum\AlphaBank\Action;

use Payum\Core\Action\ActionInterface;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Exception\RequestNotSupportedException;
use Payum\Core\Request\GetStatusInterface;
use Payum\Stripe\Constants;

class StatusAction implements ActionInterface
{
Expand All @@ -14,48 +14,55 @@ class StatusAction implements ActionInterface
*
* @param GetStatusInterface $request
*/
public function execute($request)
public function execute($request): void
{
RequestNotSupportedException::assertSupports($this, $request);
$model = ArrayObject::ensureArrayObject($request->getModel());
if ($model['error']) {
$request->markFailed();

return;
}
if (false == $model['status']) {
$request->markNew();

return;
}
if ($model['refunded']) {
if ('REFUNDED' == $model['status']) {
$request->markRefunded();

return;
}
if ('REFUSED' == $model['status'] || 'ERROR' == $model['status']) {
$request->markFailed();

return;
}
if ('CANCELED' == $model['status']) {
$request->markCanceled();

return;
}
if ('CAPTURED' == $model['status']) {
$request->markCaptured();

return;
}
if ('AUTHORIZED' == $model['status']) {
$request->markAuthorized();

return;
}
$request->markUnknown();
}

/**
* {@inheritDoc}
*/
public function supports($request)
public function supports($request): bool
{
return
$request instanceof GetStatusInterface &&
$request->getModel() instanceof \ArrayAccess
;
$request->getModel() instanceof \ArrayAccess;
}
}
}
7 changes: 7 additions & 0 deletions AlphaBankGatewayFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Dnna\Payum\AlphaBank;

use Dnna\Payum\AlphaBank\Action\Api\RequestRefundAction;
use Dnna\Payum\AlphaBank\Action\ConvertPaymentAction;
use Dnna\Payum\AlphaBank\Action\CaptureAction;
use Dnna\Payum\AlphaBank\Action\RefundAction;
Expand Down Expand Up @@ -40,6 +41,12 @@ protected function populateConfig(ArrayObject $config): void
$config['sharedSecretKey']
);
},
'payum.action.request_refund' => function (ArrayObject $config) {
return new RequestRefundAction(
$config['mid'],
$config['sharedSecretKey']
);
},
'payum.action.convert_payment' => function (ArrayObject $config) {
return new ConvertPaymentAction(
$config['sandbox'],
Expand Down
35 changes: 26 additions & 9 deletions Api.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace Dnna\Payum\AlphaBank;

use Http\Message\MessageFactory;
Expand All @@ -23,9 +24,9 @@ class Api
protected $options = [];

/**
* @param array $options
* @param array $options
* @param HttpClientInterface $client
* @param MessageFactory $messageFactory
* @param MessageFactory $messageFactory
*
* @throws \Payum\Core\Exception\InvalidArgumentException if an option is invalid
*/
Expand All @@ -37,15 +38,31 @@ public function __construct(array $options, HttpClientInterface $client, Message
}

/**
* @param array $fields
*
* @return array
* @param string $data
* @return \Psr\Http\Message\ResponseInterface
*/
public function sendXMLRequest(string $data): \Psr\Http\Message\ResponseInterface
{
$endpoint = $this->getApiEndpoint() . '/xmlpayvpos';
return $this->doRequest('POST', $endpoint, $data);
}

/**
* @param $method
* @param string $endpoint
* @param string $body
* @return \Psr\Http\Message\ResponseInterface
*/
protected function doRequest($method, array $fields)
protected function doRequest($method, string $endpoint, string $body): \Psr\Http\Message\ResponseInterface
{
$headers = [];

$request = $this->messageFactory->createRequest($method, $this->getApiEndpoint(), $headers, http_build_query($fields));
$request = $this->messageFactory->createRequest(
$method,
$endpoint,
$headers,
$body
);

$response = $this->client->send($request);

Expand All @@ -59,8 +76,8 @@ protected function doRequest($method, array $fields)
/**
* @return string
*/
protected function getApiEndpoint()
protected function getApiEndpoint(): string
{
return $this->options['sandbox'] ? 'http://sandbox.example.com' : 'http://example.com';
return $this->options['sandbox'] ? 'https://alpha.test.modirum.com/vpos' : 'https://www.alphaecommerce.gr/vpos';
}
}
9 changes: 9 additions & 0 deletions Request/Api/RequestRefund.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
namespace Dnna\Payum\AlphaBank\Request\Api;

use Payum\Core\Request\Generic;

class RequestRefund extends Generic
{

}
Loading

0 comments on commit 2155408

Please sign in to comment.