mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-08 20:22:42 +01:00
Authorize.net: New payment flow (#68)
* fixes for validation errors * authorize.net * pass livewirePaymentView & processPaymentView thru base driver * add paymentData to the interface * authorize.net credit card
This commit is contained in:
parent
364a57c857
commit
e7f41c1dba
@ -21,6 +21,7 @@ use App\Models\PaymentHash;
|
||||
use App\Models\PaymentType;
|
||||
use App\Models\SystemLog;
|
||||
use App\PaymentDrivers\AuthorizePaymentDriver;
|
||||
use App\PaymentDrivers\Common\LivewireMethodInterface;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use net\authorize\api\contract\v1\DeleteCustomerPaymentProfileRequest;
|
||||
use net\authorize\api\contract\v1\DeleteCustomerProfileRequest;
|
||||
@ -30,7 +31,7 @@ use net\authorize\api\controller\DeleteCustomerProfileController;
|
||||
/**
|
||||
* Class AuthorizeCreditCard.
|
||||
*/
|
||||
class AuthorizeCreditCard
|
||||
class AuthorizeCreditCard implements LivewireMethodInterface
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
@ -41,7 +42,7 @@ class AuthorizeCreditCard
|
||||
$this->authorize = $authorize;
|
||||
}
|
||||
|
||||
public function processPaymentView($data)
|
||||
public function paymentData(array $data): array
|
||||
{
|
||||
$tokens = ClientGatewayToken::where('client_id', $this->authorize->client->id)
|
||||
->where('company_gateway_id', $this->authorize->company_gateway->id)
|
||||
@ -54,6 +55,13 @@ class AuthorizeCreditCard
|
||||
$data['public_client_id'] = $this->authorize->init()->getPublicClientKey();
|
||||
$data['api_login_id'] = $this->authorize->company_gateway->getConfigField('apiLoginId');
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function processPaymentView($data)
|
||||
{
|
||||
$data = $this->paymentData($data);
|
||||
|
||||
return render('gateways.authorize.credit_card.pay', $data);
|
||||
}
|
||||
|
||||
@ -313,4 +321,9 @@ class AuthorizeCreditCard
|
||||
'invoices' => $vars['invoices'],
|
||||
];
|
||||
}
|
||||
|
||||
public function livewirePaymentView(array $data): string
|
||||
{
|
||||
return 'gateways.authorize.credit_card.pay_livewire';
|
||||
}
|
||||
}
|
||||
|
@ -870,4 +870,14 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function livewirePaymentView(array $data): string
|
||||
{
|
||||
return $this->payment_method->livewirePaymentView($data);
|
||||
}
|
||||
|
||||
public function processPaymentViewData(array $data): array
|
||||
{
|
||||
return $this->payment_method->paymentData($data);
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ class RFFService
|
||||
if ($return_errors) {
|
||||
return $validator->getMessageBag()->getMessages();
|
||||
}
|
||||
|
||||
session()->flash('validation_errors', $validator->getMessageBag()->getMessages());
|
||||
|
||||
return false;
|
||||
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "invoiceninja",
|
||||
"name": "@invoiceninja/invoiceninja",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
12
public/build/assets/authorize-credit-card-payment-5206050e.js
vendored
Normal file
12
public/build/assets/authorize-credit-card-payment-5206050e.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,9 +0,0 @@
|
||||
var l=Object.defineProperty;var c=(d,e,t)=>e in d?l(d,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):d[e]=t;var o=(d,e,t)=>(c(d,typeof e!="symbol"?e+"":e,t),t);/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/class s{constructor(e,t){o(this,"handleAuthorization",()=>{if(m=="1"&&document.getElementById("cvv").value.length<3){var e=$("#errors");e.show().html("<p>CVV is required</p>"),document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden");return}var t=$("#my-card"),n={};n.clientKey=this.publicKey,n.apiLoginID=this.loginId;var a={};a.cardNumber=t.CardJs("cardNumber").replace(/[^\d]/g,""),a.month=t.CardJs("expiryMonth").replace(/[^\d]/g,""),a.year=t.CardJs("expiryYear").replace(/[^\d]/g,""),a.cardCode=document.getElementById("cvv").value.replace(/[^\d]/g,"");var r={};return r.authData=n,r.cardData=a,document.getElementById("pay-now")&&(document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden")),Accept.dispatchData(r,this.responseHandler),!1});o(this,"responseHandler",e=>{if(e.messages.resultCode==="Error"){var t=0,n=$("#errors");n.show().html("<p>"+e.messages.message[t].code+": "+e.messages.message[t].text+"</p>"),document.getElementById("pay-now").disabled=!1,document.querySelector("#pay-now > svg").classList.add("hidden"),document.querySelector("#pay-now > span").classList.remove("hidden")}else if(e.messages.resultCode==="Ok"){document.getElementById("dataDescriptor").value=e.opaqueData.dataDescriptor,document.getElementById("dataValue").value=e.opaqueData.dataValue;let a=document.querySelector("input[name=token-billing-checkbox]:checked");a&&(document.getElementById("store_card").value=a.value),document.getElementById("server_response").submit()}return!1});o(this,"handle",()=>{Array.from(document.getElementsByClassName("toggle-payment-with-token")).forEach(n=>n.addEventListener("click",a=>{document.getElementById("save-card--container").style.display="none",document.getElementById("authorize--credit-card-container").style.display="none",document.getElementById("token").value=a.target.dataset.token}));let e=document.getElementById("toggle-payment-with-credit-card");e&&e.addEventListener("click",()=>{document.getElementById("save-card--container").style.display="grid",document.getElementById("authorize--credit-card-container").style.display="flex",document.getElementById("token").value=null});let t=document.getElementById("pay-now");return t&&t.addEventListener("click",n=>{let a=document.getElementById("token");a.value?this.handlePayNowAction(a.value):this.handleAuthorization()}),this});this.publicKey=e,this.loginId=t,this.cardHolderName=document.getElementById("cardholder_name")}handlePayNowAction(e){document.getElementById("pay-now").disabled=!0,document.querySelector("#pay-now > svg").classList.remove("hidden"),document.querySelector("#pay-now > span").classList.add("hidden"),document.getElementById("token").value=e,document.getElementById("server_response").submit()}}const u=document.querySelector('meta[name="authorize-public-key"]').content,i=document.querySelector('meta[name="authorize-login-id"]').content,m=document.querySelector('meta[name="authnet-require-cvv"]').content;new s(u,i).handle();
|
@ -67,7 +67,10 @@
|
||||
"src": "resources/js/clients/payment_methods/wepay-bank-account.js"
|
||||
},
|
||||
"resources/js/clients/payments/authorize-credit-card-payment.js": {
|
||||
"file": "assets/authorize-credit-card-payment-a217579b.js",
|
||||
"file": "assets/authorize-credit-card-payment-5206050e.js",
|
||||
"imports": [
|
||||
"_wait-8f4ae121.js"
|
||||
],
|
||||
"isEntry": true,
|
||||
"src": "resources/js/clients/payments/authorize-credit-card-payment.js"
|
||||
},
|
||||
|
@ -5,40 +5,65 @@
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
class AuthorizeAuthorizeCard {
|
||||
import { SimpleCard } from '@invoiceninja/simple-card';
|
||||
import { wait, instant } from '../wait';
|
||||
|
||||
class AuthorizeAuthorizeCard {
|
||||
constructor(publicKey, loginId) {
|
||||
this.publicKey = publicKey;
|
||||
this.loginId = loginId;
|
||||
this.cardHolderName = document.getElementById("cardholder_name");
|
||||
this.cardHolderName = document.getElementById('cardholder_name');
|
||||
|
||||
this.sc = new SimpleCard({
|
||||
fields: {
|
||||
card: {
|
||||
number: '#number',
|
||||
date: '#date',
|
||||
cvv: '#cvv',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
this.sc.mount();
|
||||
|
||||
this.cvvRequired = document.querySelector(
|
||||
'meta[name="authnet-require-cvv"]'
|
||||
).content;
|
||||
|
||||
}
|
||||
|
||||
handleAuthorization = () => {
|
||||
|
||||
if (cvvRequired == "1" && document.getElementById("cvv").value.length < 3) {
|
||||
var $errors = $('#errors');
|
||||
$errors.show().html("<p>CVV is required</p>");
|
||||
if (
|
||||
this.cvvRequired == '1' &&
|
||||
document.getElementById('cvv').value.length < 3
|
||||
) {
|
||||
const $errors = document.getElementById('errors');
|
||||
|
||||
if ($errors) {
|
||||
$errors.innerText = 'CVV is required';
|
||||
$errors.style.display = 'block';
|
||||
}
|
||||
|
||||
document.getElementById('pay-now').disabled = false;
|
||||
document.querySelector('#pay-now > svg').classList.add('hidden');
|
||||
document.querySelector('#pay-now > span').classList.remove('hidden');
|
||||
document
|
||||
.querySelector('#pay-now > span')
|
||||
.classList.remove('hidden');
|
||||
return;
|
||||
}
|
||||
|
||||
var myCard = $('#my-card');
|
||||
|
||||
var authData = {};
|
||||
authData.clientKey = this.publicKey;
|
||||
authData.apiLoginID = this.loginId;
|
||||
|
||||
var cardData = {};
|
||||
cardData.cardNumber = myCard.CardJs('cardNumber').replace(/[^\d]/g, '');
|
||||
cardData.month = myCard.CardJs('expiryMonth').replace(/[^\d]/g, '');
|
||||
cardData.year = myCard.CardJs('expiryYear').replace(/[^\d]/g, '');
|
||||
cardData.cardCode = document.getElementById("cvv").value.replace(/[^\d]/g, '');
|
||||
cardData.cardNumber = this.sc.value('number')?.replace(/[^\d]/g, '');
|
||||
cardData.month = this.sc.value('month')?.replace(/[^\d]/g, '');
|
||||
cardData.year = `20${this.sc.value('year')?.replace(/[^\d]/g, '')}`;
|
||||
cardData.cardCode = this.sc.value('cvv')?.replace(/[^\d]/g, '');
|
||||
|
||||
var secureData = {};
|
||||
secureData.authData = authData;
|
||||
@ -58,102 +83,112 @@ class AuthorizeAuthorizeCard {
|
||||
Accept.dispatchData(secureData, this.responseHandler);
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
handlePayNowAction(token_hashed_id) {
|
||||
document.getElementById('pay-now').disabled = true;
|
||||
document.querySelector('#pay-now > svg').classList.remove('hidden');
|
||||
document.querySelector('#pay-now > span').classList.add('hidden');
|
||||
|
||||
document.getElementById("token").value = token_hashed_id;
|
||||
document.getElementById("server_response").submit();
|
||||
document.getElementById('token').value = token_hashed_id;
|
||||
document.getElementById('server_response').submit();
|
||||
}
|
||||
|
||||
responseHandler = (response) => {
|
||||
if (response.messages.resultCode === "Error") {
|
||||
if (response.messages.resultCode === 'Error') {
|
||||
var i = 0;
|
||||
|
||||
var $errors = $('#errors'); // get the reference of the div
|
||||
$errors.show().html("<p>" + response.messages.message[i].code + ": " + response.messages.message[i].text + "</p>");
|
||||
const $errors = document.getElementById('errors'); // get the reference of the div
|
||||
|
||||
if ($errors) {
|
||||
$errors.innerText = `${response.messages.message[i].code}: ${response.messages.message[i].text}`;
|
||||
$errors.style.display = 'block';
|
||||
}
|
||||
|
||||
document.getElementById('pay-now').disabled = false;
|
||||
document.querySelector('#pay-now > svg').classList.add('hidden');
|
||||
document.querySelector('#pay-now > span').classList.remove('hidden');
|
||||
} else if (response.messages.resultCode === "Ok") {
|
||||
document
|
||||
.querySelector('#pay-now > span')
|
||||
.classList.remove('hidden');
|
||||
} else if (response.messages.resultCode === 'Ok') {
|
||||
document.getElementById('dataDescriptor').value =
|
||||
response.opaqueData.dataDescriptor;
|
||||
document.getElementById('dataValue').value =
|
||||
response.opaqueData.dataValue;
|
||||
|
||||
document.getElementById("dataDescriptor").value = response.opaqueData.dataDescriptor;
|
||||
document.getElementById("dataValue").value = response.opaqueData.dataValue;
|
||||
|
||||
let storeCard = document.querySelector('input[name=token-billing-checkbox]:checked');
|
||||
let storeCard = document.querySelector(
|
||||
'input[name=token-billing-checkbox]:checked'
|
||||
);
|
||||
|
||||
if (storeCard) {
|
||||
document.getElementById("store_card").value = storeCard.value;
|
||||
document.getElementById('store_card').value = storeCard.value;
|
||||
}
|
||||
|
||||
document.getElementById("server_response").submit();
|
||||
document.getElementById('server_response').submit();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
handle = () => {
|
||||
Array
|
||||
.from(document.getElementsByClassName('toggle-payment-with-token'))
|
||||
.forEach((element) => element.addEventListener('click', (e) => {
|
||||
document
|
||||
.getElementById('save-card--container').style.display = 'none';
|
||||
document
|
||||
.getElementById('authorize--credit-card-container').style.display = 'none';
|
||||
Array.from(
|
||||
document.getElementsByClassName('toggle-payment-with-token')
|
||||
).forEach((element) =>
|
||||
element.addEventListener('click', (e) => {
|
||||
document.getElementById('save-card--container').style.display =
|
||||
'none';
|
||||
document.getElementById(
|
||||
'authorize--credit-card-container'
|
||||
).style.display = 'none';
|
||||
|
||||
document
|
||||
.getElementById('token').value = e.target.dataset.token;
|
||||
}));
|
||||
document.getElementById('token').value = e.target.dataset.token;
|
||||
})
|
||||
);
|
||||
|
||||
let payWithCreditCardToggle = document.getElementById('toggle-payment-with-credit-card');
|
||||
let payWithCreditCardToggle = document.getElementById(
|
||||
'toggle-payment-with-credit-card'
|
||||
);
|
||||
|
||||
if (payWithCreditCardToggle) {
|
||||
payWithCreditCardToggle
|
||||
.addEventListener('click', () => {
|
||||
document
|
||||
.getElementById('save-card--container').style.display = 'grid';
|
||||
document
|
||||
.getElementById('authorize--credit-card-container').style.display = 'flex';
|
||||
payWithCreditCardToggle.addEventListener('click', () => {
|
||||
document.getElementById('save-card--container').style.display =
|
||||
'grid';
|
||||
document.getElementById(
|
||||
'authorize--credit-card-container'
|
||||
).style.display = 'flex';
|
||||
|
||||
document
|
||||
.getElementById('token').value = null;
|
||||
});
|
||||
document.getElementById('token').value = null;
|
||||
});
|
||||
}
|
||||
|
||||
let payNowButton = document.getElementById('pay-now');
|
||||
|
||||
if (payNowButton) {
|
||||
payNowButton
|
||||
.addEventListener('click', (e) => {
|
||||
let token = document.getElementById('token');
|
||||
payNowButton.addEventListener('click', (e) => {
|
||||
let token = document.getElementById('token');
|
||||
|
||||
token.value
|
||||
? this.handlePayNowAction(token.value)
|
||||
: this.handleAuthorization();
|
||||
});
|
||||
token.value
|
||||
? this.handlePayNowAction(token.value)
|
||||
: this.handleAuthorization();
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const publicKey = document.querySelector(
|
||||
'meta[name="authorize-public-key"]'
|
||||
).content;
|
||||
function boot() {
|
||||
const publicKey = document.querySelector(
|
||||
'meta[name="authorize-public-key"]'
|
||||
).content;
|
||||
|
||||
const loginId = document.querySelector(
|
||||
'meta[name="authorize-login-id"]'
|
||||
).content;
|
||||
const loginId = document.querySelector(
|
||||
'meta[name="authorize-login-id"]'
|
||||
).content;
|
||||
|
||||
const cvvRequired = document.querySelector(
|
||||
'meta[name="authnet-require-cvv"]'
|
||||
).content;
|
||||
/** @handle */
|
||||
new AuthorizeAuthorizeCard(publicKey, loginId).handle();
|
||||
}
|
||||
|
||||
instant() ? boot() : wait('#authorize-net-credit-card-payment').then(() => boot());
|
||||
|
||||
/** @handle */
|
||||
new AuthorizeAuthorizeCard(publicKey, loginId).handle();
|
||||
|
@ -3,6 +3,7 @@
|
||||
@section('gateway_head')
|
||||
<meta name="authorize-public-key" content="{{ $public_client_id }}">
|
||||
<meta name="authorize-login-id" content="{{ $api_login_id }}">
|
||||
<meta name="instant-payment" content="yes" />
|
||||
|
||||
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
|
||||
<meta name="authnet-require-cvv" content="{{ $gateway->company_gateway->require_cvv }}">
|
||||
|
@ -1,11 +1,13 @@
|
||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6"
|
||||
style="display: flex!important; justify-content: center!important;" id="authorize--credit-card-container">
|
||||
<div class="card-js" id="my-card" data-capture-name="true">
|
||||
<input class="name" id="cardholder_name" name="card-holders-name" placeholder="{{ ctrans('texts.name')}}">
|
||||
<input class="card-number my-custom-class" id="card_number" name="card-number">
|
||||
<input class="expiry-month" name="expiry-month" id="expiration_month" autocomplete="cc-exp-month" x-autocompletetype="cc-exp-month">
|
||||
<input class="expiry-year" name="expiry-year" id="expiration_year" autocomplete="cc-exp-year" x-autocompletetype="cc-exp-year">
|
||||
<input class="cvc" name="cvc" id="cvv">
|
||||
<div class="card-js" id="my-card" data-capture-name="true">
|
||||
<input class="input w-full" id="cardholder_name" name="card_holders_name"
|
||||
placeholder="{{ ctrans('texts.name')}}">
|
||||
<input type="text" class="input w-full" id="number" placeholder="0000 0000 0000 0000">
|
||||
<div class="flex items-center gap-2">
|
||||
<input type="text" class="input w-1/2" id="date" placeholder="MM/YY">
|
||||
<input type="text" class="input w-1/2" id="cvv" placeholder="000">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="errors"></div>
|
||||
|
Loading…
Reference in New Issue
Block a user