Skip to content

Commit

Permalink
Add charge card method (#3)
Browse files Browse the repository at this point in the history
* Add bin filter

* Add GitHub actions

* Fixing condition php

* Implement charge method

* Implement charge method
  • Loading branch information
nuradiyana authored Sep 6, 2021
1 parent 2aa0f2b commit 09dcdd8
Show file tree
Hide file tree
Showing 9 changed files with 325 additions and 11 deletions.
12 changes: 12 additions & 0 deletions src/Contracts/CardInputFactoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Ziswapp\Payment\Contracts;

use Ziswapp\Payment\Input\ChargeCardInput;

interface CardInputFactoryInterface extends InputInterface
{
public function fromChargeInput(ChargeCardInput $input): self;
}
12 changes: 12 additions & 0 deletions src/Contracts/CardOutputFactoryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Ziswapp\Payment\Contracts;

use Ziswapp\Payment\Output\ChargeCardOutput;

interface CardOutputFactoryInterface
{
public function fromChargeArray(array $data): ChargeCardOutput;
}
15 changes: 15 additions & 0 deletions src/Contracts/CardPaymentInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Ziswapp\Payment\Contracts;

use Ziswapp\Payment\Input\ChargeCardInput;

interface CardPaymentInterface
{
/**
* @return mixed
*/
public function charge(ChargeCardInput $input);
}
48 changes: 48 additions & 0 deletions src/Input/ChargeCardInput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Ziswapp\Payment\Input;

use Ziswapp\Payment\ValueObject\Transaction;

final class ChargeCardInput extends TransactionInput
{
private string $token;

private bool $authentication;

private bool $savedToken;

private array $allowedBins;

public function __construct(Transaction $transaction, string $token, bool $authentication, bool $savedToken = false, array $allowedBins = [])
{
$this->token = $token;
$this->authentication = $authentication;
$this->savedToken = $savedToken;
$this->allowedBins = $allowedBins;

parent::__construct($transaction);
}

public function getToken(): string
{
return $this->token;
}

public function isAuthentication(): bool
{
return $this->authentication;
}

public function isSavedToken(): bool
{
return $this->savedToken;
}

public function getAllowedBins(): array
{
return $this->allowedBins;
}
}
55 changes: 55 additions & 0 deletions src/Output/ChargeCardOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Ziswapp\Payment\Output;

use DateTimeInterface;

final class ChargeCardOutput extends TransactionOutput
{
private ?string $redirectUrl = null;

private string $fraudStatus;

private DateTimeInterface $transactionDate;

public static function create(
string $transactionId,
string $orderId,
string $status,
string $fraudStatus,
float $amount,
DateTimeInterface $transactionDate,
?string $redirectUrl = null,
array $originalOutput = []
): self {
$self = new self();

$self->transactionId = $transactionId;
$self->orderId = $orderId;
$self->status = $status;
$self->fraudStatus = $fraudStatus;
$self->amount = $amount;
$self->redirectUrl = $redirectUrl;
$self->transactionDate = $transactionDate;
$self->originalOutput = $originalOutput;

return $self;
}

public function getRedirectUrl(): ?string
{
return $this->redirectUrl;
}

public function getFraudStatus(): string
{
return $this->fraudStatus;
}

public function getTransactionDate(): DateTimeInterface
{
return $this->transactionDate;
}
}
38 changes: 37 additions & 1 deletion src/Providers/Midtrans/MidtransClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,32 @@

namespace Ziswapp\Payment\Providers\Midtrans;

use InvalidArgumentException;
use Ziswapp\Payment\Output\CStoreOutput;
use Ziswapp\Payment\Output\EWalletOutput;
use Ziswapp\Payment\Input\ChargeCardInput;
use Ziswapp\Payment\Output\ChargeCardOutput;
use Ziswapp\Payment\Input\CardBinFilterInput;
use Ziswapp\Payment\Output\CheckStatusOutput;
use Ziswapp\Payment\Output\CardBinFilterOutput;
use Ziswapp\Payment\Exceptions\PaymentException;
use Ziswapp\Payment\Output\VirtualAccountOutput;
use Ziswapp\Payment\Input\CStoreTransactionInput;
use Ziswapp\Payment\Input\EWalletTransactionInput;
use Ziswapp\Payment\Contracts\CardPaymentInterface;
use Ziswapp\Payment\Contracts\UtilOperationInterface;
use Ziswapp\Payment\Input\CheckStatusTransactionInput;
use Ziswapp\Payment\Contracts\CardInputFactoryInterface;
use Ziswapp\Payment\Input\CancelPaymentTransactionInput;
use Ziswapp\Payment\Contracts\CardOutputFactoryInterface;
use Ziswapp\Payment\Input\VirtualAccountTransactionInput;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;

final class MidtransClient extends Client implements UtilOperationInterface
final class MidtransClient extends Client implements UtilOperationInterface, CardPaymentInterface
{
/**
* @throws ClientExceptionInterface
Expand Down Expand Up @@ -146,4 +152,34 @@ public function binInfo(CardBinFilterInput $input): CardBinFilterOutput

return $this->outputFactory->fromFilterBinArray($data);
}

/**
* @throws ClientExceptionInterface
* @throws DecodingExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ServerExceptionInterface
* @throws TransportExceptionInterface
*/
public function charge(ChargeCardInput $input): ChargeCardOutput
{
if (! $this->inputFactory instanceof CardInputFactoryInterface) {
throw new InvalidArgumentException(\sprintf('Input factory must be instance of `%s`', CardInputFactoryInterface::class));
}

$input = $this->inputFactory->fromChargeInput($input);

$response = $this->executeRequest('POST', '/v2/charge', $input->requestBody());

$data = $response->toArray();

if ((int) $data['status_code'] !== 200 && (int) $data['status_code'] !== 201) {
throw new PaymentException($response, (int) $data['status_code'], $data['status_message']);
}

if (! $this->outputFactory instanceof CardOutputFactoryInterface) {
throw new InvalidArgumentException(\sprintf('Output factory must be instance of `%s`', CardOutputFactoryInterface::class));
}

return $this->outputFactory->fromChargeArray($data);
}
}
29 changes: 24 additions & 5 deletions src/Providers/Midtrans/MidtransInputFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@
use Ziswapp\Payment\Enum\CStore;
use Ziswapp\Payment\Enum\EWallet;
use Ziswapp\Payment\Enum\VirtualAccount;
use Ziswapp\Payment\Input\ChargeCardInput;
use Ziswapp\Payment\ValueObject\Transaction;
use Ziswapp\Payment\Contracts\InputInterface;
use Ziswapp\Payment\Input\CStoreTransactionInput;
use Ziswapp\Payment\Input\EWalletTransactionInput;
use Ziswapp\Payment\Contracts\CardInputFactoryInterface;
use Ziswapp\Payment\Input\VirtualAccountTransactionInput;
use Ziswapp\Payment\Contracts\PaymentInputFactoryInterface;
use Ziswapp\Payment\Providers\Midtrans\Concerns\InputRequestBody;

final class MidtransInputFactory implements InputInterface, PaymentInputFactoryInterface
final class MidtransInputFactory implements InputInterface, PaymentInputFactoryInterface, CardInputFactoryInterface
{
use InputRequestBody;

Expand All @@ -36,7 +38,7 @@ public function fromCStoreInput(CStoreTransactionInput $input): self
{
$this->setTransaction($input->getTransaction());

$this->params = array_merge($this->defaultParams(), [
$this->params = \array_merge($this->defaultParams(), [
'payment_type' => 'cstore',
'cstore' => [
'store' => CStore::midtransCode(
Expand All @@ -54,15 +56,15 @@ public function fromVirtualAccountInput(VirtualAccountTransactionInput $input):
$this->setTransaction($input->getTransaction());

if ($input->getAccount()->getProviderCode() === VirtualAccount::MANDIRI()) {
$this->params = array_merge($this->defaultParams(), [
$this->params = \array_merge($this->defaultParams(), [
'payment_type' => 'echannel',
'echannel' => [
'bill_info1' => \sprintf('Payment for transaction %s', $input->getTransaction()->getId()),
'bill_info2' => 'debt',
],
]);
} else {
$this->params = array_merge($this->defaultParams(), [
$this->params = \array_merge($this->defaultParams(), [
'bank_transfer' => [
'bank' => VirtualAccount::midtransCode(
$input->getAccount()->getProviderCode()
Expand All @@ -80,7 +82,7 @@ public function fromEWalletInput(EWalletTransactionInput $input): self
{
$this->setTransaction($input->getTransaction());

$this->params = array_merge($this->defaultParams(), [
$this->params = \array_merge($this->defaultParams(), [
'payment_type' => EWallet::midtransCode(
$input->getWallet()->getProviderCode()
),
Expand All @@ -99,6 +101,23 @@ public function fromEWalletInput(EWalletTransactionInput $input): self
return $this;
}

public function fromChargeInput(ChargeCardInput $input): self
{
$this->setTransaction($input->getTransaction());

$this->params = \array_merge($this->defaultParams(), [
'payment_type' => 'credit_card',
'credit_card' => [
'token_id' => $input->getToken(),
'authentication' => $input->isAuthentication(),
'save_token_id' => $input->isSavedToken(),
'bins' => $input->getAllowedBins(),
],
]);

return $this;
}

public function requestBody(): array
{
if ($this->params) {
Expand Down
40 changes: 35 additions & 5 deletions src/Providers/Midtrans/MidtransOutputFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@

namespace Ziswapp\Payment\Providers\Midtrans;

use DateTime;
use Psl\Type;
use Ziswapp\Payment\Output\CStoreOutput;
use Ziswapp\Payment\Output\EWalletOutput;
use Ziswapp\Payment\Output\ChargeCardOutput;
use Ziswapp\Payment\Output\CheckStatusOutput;
use Ziswapp\Payment\Output\CardBinFilterOutput;
use Ziswapp\Payment\Output\VirtualAccountOutput;
use Ziswapp\Payment\Contracts\OutputFactoryInterface;
use Ziswapp\Payment\Contracts\CardOutputFactoryInterface;

final class MidtransOutputFactory implements OutputFactoryInterface
final class MidtransOutputFactory implements OutputFactoryInterface, CardOutputFactoryInterface
{
private function __construct()
{
Expand Down Expand Up @@ -155,10 +158,37 @@ public function fromEWalletArray(array $data): EWalletOutput
public function fromFilterBinArray(array $data): CardBinFilterOutput
{
$data = Type\shape([
'bin' => Type\non_empty_string(),
'bin_type' => Type\non_empty_string(),
], true)->coerce($data['data']);
'data' => Type\shape([
'bin' => Type\non_empty_string(),
'bin_type' => Type\non_empty_string(),
], true),
])->coerce($data);

return CardBinFilterOutput::create($data['bin'], $data['bin_type'], $data);
return CardBinFilterOutput::create($data['data']['bin'], $data['data']['bin_type'], $data['data']);
}

public function fromChargeArray(array $data): ChargeCardOutput
{
$data = Type\shape([
'transaction_id' => Type\non_empty_string(),
'order_id' => Type\non_empty_string(),
'redirect_url' => Type\optional(Type\nullable(Type\string())),
'gross_amount' => Type\non_empty_string(),
'fraud_status' => Type\non_empty_string(),
'transaction_status' => Type\non_empty_string(),
'transaction_time' => Type\non_empty_string(),
], true)->coerce($data);

/** @noinspection PhpUnhandledExceptionInspection */
return ChargeCardOutput::create(
$data['transaction_id'],
$data['order_id'],
$data['transaction_status'],
$data['fraud_status'],
(float) $data['gross_amount'],
new DateTime($data['transaction_time']),
$data['redirect_url'] ?? null,
$data
);
}
}
Loading

0 comments on commit 09dcdd8

Please sign in to comment.