File: /var/www/vhost/disk-apps/teamdemo.sports-crowd.com/app/Core/Payment/Methods/Nmi/NmiStrategy.php
<?php
declare(strict_types=1);
namespace App\Core\Payment\Methods\Nmi;
use App\Core\Payment\Entities\Payment;
use App\Core\Payment\Entities\PaymentIntentResponse;
use App\Core\Payment\Entities\PaymentRetrieveResponse;
use App\Core\Payment\PaymentMethodInterface;
use App\Core\Payment\PaymentStatusEnum;
use GuzzleHttp\Client;
use SimpleXMLElement;
class NmiStrategy implements PaymentMethodInterface
{
const PAYMENT_STATUS = [
'0'=> PaymentStatusEnum::PENDING,
'1' => PaymentStatusEnum::CONFIRMED,
'2' => PaymentStatusEnum::DECLINED,
'3'=> PaymentStatusEnum::REJECTED,
];
private $parameters;
public function __construct(
$parameters
) {
$this->parameters = $parameters;
}
public function pay(Payment $payment): PaymentIntentResponse
{
$payment->amount()->setCurrency($this->parameters->currency);
$paymentIntent = $this->createPaymentIntent($payment);
// TODO: this allows to get token-id but we don't need it
$url = $paymentIntent->{'form-url'};
$url_path = parse_url($url, PHP_URL_PATH);
$tokenID = pathinfo($url_path, PATHINFO_BASENAME);
$paymentIntentResponse = new PaymentIntentResponse(
PaymentIntentResponse::ACTION_SHOW,
$paymentIntent->{'transaction-id'}
);
$data = [
'total_price' => $payment->amount()->total(),
'form_action' => $url,
'gatewayImageUrl' => $this->parameters->image
];
$paymentIntentResponse->setView("nmi.webcheckout");
$paymentIntentResponse->setData($data);
return $paymentIntentResponse;
}
public function retrieve(Payment $payment): PaymentRetrieveResponse
{
try {
if (request()->has('token-id')) {
$this->completePayment($payment);
}
$gatewayResponse = $this->retrievePayment($payment->paymentGatewayTxId());
$status = PaymentStatusEnum::PENDING;
$message = '';
if ($gatewayResponse->transaction) {
$status = self::PAYMENT_STATUS[$gatewayResponse->transaction->action->success];
if (is_string($gatewayResponse->transaction->action->response_text)) {
$message = (string) $gatewayResponse->transaction->action->response_text;
}
}
return new PaymentRetrieveResponse(
$payment->paymentGatewayTxId(),
$status,
$message
);
} catch (\Throwable $th) {
return new PaymentRetrieveResponse(
$payment->paymentGatewayTxId(),
PaymentStatusEnum::PENDING,
$th->getMessage()
);
}
}
private function createPaymentIntent($payment)
{
$redirectUrl = config('app.url') .
'/store/payment?paymentGatewayId=' .
$payment->paymentGatewayId() .
'&reference=' .$payment->reference();
$xmlRequest = new \DOMDocument('1.0', 'utf-8');
$xmlRequest->preserveWhiteSpace = false;
$xmlRequest->formatOutput = true;
$sales = $xmlRequest->createElement('sale');
$apikey = $xmlRequest->createElement('api-key', $this->parameters->api_key);
$redirect = $xmlRequest->createElement('redirect-url', htmlspecialchars($redirectUrl));
$amount = $xmlRequest->createElement('amount', (string)$payment->amount()->total());
$address = $xmlRequest->createElement('ip-address', $_SERVER["REMOTE_ADDR"]);
$currency = $xmlRequest->createElement('currency', $payment->amount()->currency());
$order_id = $xmlRequest->createElement('order-id', $payment->reference());
$sales->appendChild($apikey);
$sales->appendChild($redirect);
$sales->appendChild($amount);
$sales->appendChild($address);
$sales->appendChild($currency);
$sales->appendChild($order_id);
$xmlRequest->appendChild($sales);
return $this->sendXMLviaCurl($xmlRequest, $this->parameters->gw_url_prd);
}
private function sendXMLviaCurl($xmlRequest, $gatewayURL)
{
$httpClient = new Client();
$response = $httpClient->post(
$gatewayURL,
[
'headers' => [
'Content-type' => 'text/xml',
'Accept' => 'application/xml'
],
'body' => $xmlRequest->saveXML(),
]
)->getBody()->getContents();
return json_decode(json_encode(new SimpleXMLElement($response)));
}
private function completePayment(Payment $payment)
{
if (request()->has('token-id')) {
$xmlRequest = new \DOMDocument('1.0', 'utf-8');
$xmlRequest->preserveWhiteSpace = false;
$xmlRequest->formatOutput = true;
$xmlCompleteTransaction = $xmlRequest->createElement('complete-action');
$apikey = $xmlRequest->createElement('api-key', $this->parameters->api_key);
$tokenID = $xmlRequest->createElement('token-id', request()->get('token-id'));
$xmlCompleteTransaction->appendChild($apikey);
$xmlCompleteTransaction->appendChild($tokenID);
$xmlRequest->appendChild($xmlCompleteTransaction);
$response = $this->sendXMLviaCurl($xmlRequest, $this->parameters->gw_url_prd);
}
}
private function retrievePayment($paymentTxId)
{
$httpClient = new Client();
$response = $httpClient->post(
'https://secure.nmi.com/api/query.php?security_key=' .
$this->parameters->api_key .
'&transaction_id=' . $paymentTxId,
[
'headers' => ['Accept' => 'application/xml']
]
)->getBody()->getContents();
return json_decode(json_encode(new SimpleXMLElement($response)));
}
}