Skip to content
This repository has been archived by the owner on Nov 12, 2024. It is now read-only.

Commit

Permalink
Merge pull request #11 from revosystems/feature/REV-11510
Browse files Browse the repository at this point in the history
feature: add operation to tokenize cards and add charge with tokenized card without interface.
  • Loading branch information
BadChoice authored Jun 7, 2023
2 parents 01b3f03 + ede04ca commit 9ca3998
Show file tree
Hide file tree
Showing 16 changed files with 323 additions and 29 deletions.
6 changes: 4 additions & 2 deletions src/Http/Controllers/WebhookController.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Revosystems\Redsys\Lib\Model\Element\RESTOperationElement;
use Revosystems\Redsys\Models\ChargeResult;
use Revosystems\Redsys\Services\RedsysChargeRequest;
use Revosystems\Redsys\Services\RedsysException;
use Revosystems\Redsys\Services\RedsysPayment;
Expand Down Expand Up @@ -41,7 +42,7 @@ public function webhook(Request $request) : void
return;
}
Log::debug('[REDSYS] Authenticate charge success');
$this->chargeSucceeded($request);
$this->chargeSucceeded($request, $result);
return;
} catch (RedsysException $e) {
$this->chargeFailed($request, "Charge failed {$e->getMessage()}");
Expand All @@ -66,8 +67,9 @@ protected function chargeFailed(Request $request, $errorMessage)
Cache::put(WebhookHandler::ORDERS_CACHE_KEY . "{$request->get('paymentReference')}.result", 'FAILED', Carbon::now()->addMinutes(30));
}

protected function chargeSucceeded(Request $request)
protected function chargeSucceeded(Request $request, ChargeResult $result)
{
Cache::put(WebhookHandler::ORDERS_CACHE_KEY . "{$request->get('paymentReference')}.chargeResult", serialize($result), Carbon::now()->addMinutes(30));
Cache::put(WebhookHandler::ORDERS_CACHE_KEY . "{$request->get('paymentReference')}.result", 'SUCCESS', Carbon::now()->addMinutes(30));
}

Expand Down
3 changes: 2 additions & 1 deletion src/Http/Livewire/CheckStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public function checkStatus()
return;
}
if ($result === 'SUCCESS') {
RedsysChargePayment::get($this->paymentReference)->payHandler->onPaymentSucceed($this->paymentReference);
$chargeResult = unserialize(Cache::get(WebhookHandler::ORDERS_CACHE_KEY . "{$this->paymentReference}.chargeResult"));
RedsysChargePayment::get($this->paymentReference)->payHandler->onPaymentSucceed($this->paymentReference, $chargeResult);
}
}
}
49 changes: 49 additions & 0 deletions src/Http/Livewire/RedsysTokenizeForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Revosystems\Redsys\Http\Livewire;

use Livewire\Component;
use Revosystems\Redsys\Models\ChargeResult;
use Revosystems\Redsys\Services\RedsysChargePayment;
use Revosystems\Redsys\Services\RedsysChargeRequest;
use Revosystems\Redsys\Models\RedsysPaymentGateway;

class RedsysTokenizeForm extends Component
{
protected $listeners = [
'onCardFormSubmit',
'onTokenizeCompleted',
];

public $paymentReference;
public $iframeUrl;
public $redsysFormId;

public function mount(string $redsysFormId, string $paymentReference)
{
$this->redsysFormId = $redsysFormId;
$this->paymentReference = $paymentReference;
$this->iframeUrl = RedsysPaymentGateway::get()->isTestEnvironment() ? 'https://sis-t.redsys.es:25443/sis/NC/sandbox/redsysV2.js' : 'https://sis.redsys.es/sis/NC/redsysV2.js';
}

public function render()
{
return view('redsys::livewire.redsys-tokenize-form');
}

public function onTokenizeCompleted(ChargeResult $data) : void
{
RedsysChargePayment::get($this->paymentReference)->payHandler->onPaymentSucceed($this->paymentReference, $data);
}

public function onCardFormSubmit(string $operationId, array $extraInfo) : void
{
$chargeRequest = RedsysChargeRequest::makeWithOperationId($this->paymentReference, $operationId, $extraInfo);
$chargeRequest->customerToken = 'customer_token';
$this->emit('payResponse', RedsysPaymentGateway::get()->tokenizeCard(
RedsysChargePayment::get($this->paymentReference),
$chargeRequest
)->gatewayResponse);
}

}
21 changes: 21 additions & 0 deletions src/Models/RedsysPaymentGateway.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,27 @@ public function render(RedsysChargePayment $chargePayment, $customerToken)
])->render();
}

public function renderTokenize(RedsysChargePayment $chargePayment)
{
$paymentReference = RedsysChargeRequest::generatePaymentReference();
$chargePayment->persist($paymentReference);
return view('redsys::tokenize.index', [
'paymentReference' => $paymentReference,
'chargePayment' => $chargePayment,
'redsysConfig' => $this->config,
])->render();
}

public function tokenizeCard(RedsysChargePayment $chargePayment, RedsysChargeRequest $chargeRequest) : ChargeResult
{
$operationId = $chargeRequest->operationId;
$cardId = $chargeRequest->cardId;
if ($operationId === -1 || (! $operationId && ! $cardId)) {
return new ChargeResult(false);
}
return (new RedsysRequestInit($this->config))->handle($chargePayment, $chargeRequest);
}

public function charge(RedsysChargePayment $chargePayment, RedsysChargeRequest $chargeRequest) : ChargeResult
{
$operationId = $chargeRequest->operationId;
Expand Down
2 changes: 1 addition & 1 deletion src/Models/RedsysPaymentHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

interface RedsysPaymentHandler
{
public function onPaymentSucceed(string $reference);
public function onPaymentSucceed(string $reference, ?ChargeResult $result = null);
public function onPaymentFailed(?string $error = null);
}
2 changes: 2 additions & 0 deletions src/RedsysServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Revosystems\Redsys\Http\Livewire\CheckStatus;
use Revosystems\Redsys\Http\Livewire\GooglePayButton;
use Revosystems\Redsys\Http\Livewire\RedsysForm;
use Revosystems\Redsys\Http\Livewire\RedsysTokenizeForm;
use Revosystems\Redsys\View\Components\RadioSelector;
use FA;

Expand All @@ -26,6 +27,7 @@ public function boot()
]);

Livewire::component('redsys-form', RedsysForm::class);
Livewire::component('redsys-tokenize-form', RedsysTokenizeForm::class);
Livewire::component('check-status', CheckStatus::class);
Livewire::component('apple-pay-button', ApplePayButton::class);
Livewire::component('google-pay-button', GooglePayButton::class);
Expand Down
7 changes: 7 additions & 0 deletions src/Services/RedsysChargeRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ public static function makeWithOperationId($paymentReference, string $operationI
return $chargeRequest;
}

public static function makeWithCardForCOF(string $cardId, $paymentReference = null) : self
{
$chargeRequest = new self($paymentReference);
$chargeRequest->cardId = $cardId;
return $chargeRequest;
}

public static function generatePaymentReference() : string
{
return substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 10)), 0, 12);
Expand Down
2 changes: 2 additions & 0 deletions src/Services/RedsysRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ protected function getResponse(RESTResponseMessage $response)
return [
"result" => $response->getResult(),
"operation" => $response->getResult() !== 'KO' ? $response->getOperation() : null,
'customerToken' => $response->getOperation()->getMerchantIdentifier(),
'customerTokenExpiration' => $response->getOperation()->getExpiryDate()
];
}
}
16 changes: 16 additions & 0 deletions src/Services/RedsysTokenizeCardChargePayment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php


namespace Revosystems\Redsys\Services;

use Revosystems\Redsys\Models\RedsysPaymentHandler;

class RedsysTokenizeCardChargePayment extends RedsysChargePayment
{

public function __construct(RedsysPaymentHandler $payHandler, string $externalReference, string $tenant)
{
parent::__construct($payHandler, $externalReference, $tenant, 0, 'EUR');
}

}
3 changes: 3 additions & 0 deletions src/Services/RequestAuthorization.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ protected function getAuthorizationChargeResult(RedsysChargePayment $chargePayme
if ($chargeRequest->customerToken) {
$operationRequest->createReference();
}
if ($chargeRequest->cardId && !$chargeRequest->extraInfo) {
$operationRequest->useDirectPayment();
}

$response = RedsysRest::make(RESTTrataRequestService::class, $this->config->key, $this->config->test)->sendOperation($operationRequest);
$result = $response->getResult();
Expand Down
34 changes: 18 additions & 16 deletions src/Services/RequestAuthorizationV2.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,24 @@ protected function setEMV3DSParamsV2(RedsysChargePayment $chargePayment, RedsysC
if ($threeDSMethodURL) {
// implementar nou flux
}
$operationRequest->setEMV3DSParamsV2(
$protocolVersion,
request()->header('Accept'),
request()->header('User-Agent'),
"true", "true",
request()->ip(),
// request()->header('Accept-Language', 'es-ES'), // navigator.language
"es-ES",
(string)$chargeRequest->extraInfo['browser_color_depth'],
(string)$chargeRequest->extraInfo['browser_height'],
(string)$chargeRequest->extraInfo['browser_width'],
(string)$chargeRequest->extraInfo['browser_tz'],
$response->getThreeDSServerTransID(),
$this->getWebhookUrl($chargePayment, $chargeRequest->paymentReference),
$threeDSMethodURL ? 'N' : 'U'
);
if ($chargeRequest->extraInfo){
$operationRequest->setEMV3DSParamsV2(
$protocolVersion,
request()->header('Accept'),
request()->header('User-Agent'),
"true", "true",
request()->ip(),
// request()->header('Accept-Language', 'es-ES'), // navigator.language
"es-ES",
(string)$chargeRequest->extraInfo['browser_color_depth'],
(string)$chargeRequest->extraInfo['browser_height'],
(string)$chargeRequest->extraInfo['browser_width'],
(string)$chargeRequest->extraInfo['browser_tz'],
$response->getThreeDSServerTransID(),
$this->getWebhookUrl($chargePayment, $chargeRequest->paymentReference),
$threeDSMethodURL ? 'N' : 'U'
);
}
// if (auth()->user()->email) {
// $operationRequest->addEmvParameter(RESTConstants::$REQUEST_MERCHANT_EMV3DS_EMAIL, auth()->user()->email);
// }
Expand Down
3 changes: 3 additions & 0 deletions src/resources/views/livewire/redsys-tokenize-form.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div :id="'new-card-mode'" :name="'mode'">
@include('redsys::tokenize.iframe', compact('iframeUrl'))
</div>
18 changes: 9 additions & 9 deletions src/resources/views/redsys/main.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
enableButtons(enable) {
if({{$googlePayEnabled}}) enableGooglePayButton(enable)
if({{$applePayEnabled}}) enableApplePayButton(enable)
this.updateButtom(document.getElementById('redsys-hosted-pay-button'), enable)
Array.from(document.getElementsByClassName('token-card')).forEach(elem => this.updateButtom(elem, enable))
this.updateButton(document.getElementById('redsys-hosted-pay-button'), enable)
Array.from(document.getElementsByClassName('token-card')).forEach(elem => this.updateButton(elem, enable))
},
updateButtom(elem, enable) {
updateButton(elem, enable) {
elem.style.pointerEvents = enable ? 'all' : 'none'
elem.style.opacity = enable ? 1 : 0.5
}
Expand Down Expand Up @@ -172,22 +172,22 @@ function submitChallengeForm() {
})
let redsysErrors = {
"msg1": "Ha de rellenar los datos de la tarjeta",
"msg1": "Debe rellenar los datos de la tarjeta",
"msg2": "La tarjeta es obligatoria",
"msg3": "La tarjeta ha de ser numérica",
"msg3": "La tarjeta debe ser numérica",
"msg4": "La tarjeta no puede ser negativa",
"msg5": "El mes de caducidad de la tarjeta es obligatorio",
"msg6": "El mes de caducidad de la tarjeta ha de ser numérico",
"msg6": "El mes de caducidad de la tarjeta debe ser numérico",
"msg7": "El mes de caducidad de la tarjeta es incorrecto",
"msg8": "El año de caducidad de la tarjeta es obligatorio",
"msg9": "El año de caducidad de la tarjeta ha de ser numérico",
"msg9": "El año de caducidad de la tarjeta debe ser numérico",
"msg10": "El año de caducidad de la tarjeta no puede ser negativo",
"msg11": "El código de seguridad de la tarjeta no tiene la longitud correcta",
"msg12": "El código de seguridad de la tarjeta ha de ser numérico",
"msg12": "El código de seguridad de la tarjeta debe ser numérico",
"msg13": "El código de seguridad de la tarjeta no puede ser negativo",
"msg14": "El código de seguridad no es necesario para su tarjeta",
"msg15": "La longitud de la tarjeta no es correcta",
"msg16": "Debe Introducir un número de tarjeta válido (sin espacios ni guiones).",
"msg16": "Debe introducir un número de tarjeta válido (sin espacios ni guiones).",
"msg17": "Validación incorrecta por parte del comercio"
}
</script>
5 changes: 5 additions & 0 deletions src/resources/views/tokenize/iframe.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script src="{{ $iframeUrl }}"></script>
<div id="{{ $redsysFormId }}" style="height: 500px; margin: auto;" wire:ignore>
</div>
<input type="hidden" id="token"/>
<input type="hidden" id="errorCode"/>
19 changes: 19 additions & 0 deletions src/resources/views/tokenize/index.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@extends(config('redsys.indexLayout'))

@section('redsys-head')
<script src="https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js" defer></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
{!! \Khill\FontAwesome\FontAwesome::css() !!}
@endsection

@section('content')

<div class="w-full flex flex-col space-y-4 h-full" style="height: 100%; min-height: 200px; margin-top: 24px">
@include('redsys::tokenize.main', [
'redsysFormId' => 'redsys-init-form',
'redsysConfig' => $redsysConfig,
'paymentReference' => $paymentReference,
'chargePayment' => $chargePayment,
])
</div>
@endsection
Loading

0 comments on commit 9ca3998

Please sign in to comment.