powerboard

This commit is contained in:
David Bomba 2024-09-08 19:06:31 +10:00
parent a9aa6aea87
commit 1f3c37a76b
10 changed files with 609 additions and 303 deletions

28
app/Helpers/Sanitizer.php Normal file
View File

@ -0,0 +1,28 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Helpers;
class Sanitizer
{
public static function removeBlanks($input): array
{
foreach ($input as &$value) {
if (is_array($value)) {
// Recursively apply the filter to nested arrays
$value = self::removeBlanks($value);
}
}
// Use array_filter to remove empty or null values
return array_filter($input);
}
}

View File

@ -12,15 +12,18 @@
namespace App\PaymentDrivers\CBAPowerBoard;
use App\Exceptions\PaymentFailed;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\GatewayType;
use App\Models\Payment;
use App\Models\PaymentType;
use App\Models\SystemLog;
use App\Models\GatewayType;
use App\Models\PaymentHash;
use App\Models\PaymentType;
use App\Jobs\Util\SystemLogger;
use App\Exceptions\PaymentFailed;
use App\PaymentDrivers\CBAPowerBoardPaymentDriver;
use App\PaymentDrivers\CBAPowerBoard\Models\Charge;
use App\PaymentDrivers\Common\LivewireMethodInterface;
use App\PaymentDrivers\CBAPowerBoard\Models\PaymentSource;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
class CreditCard implements LivewireMethodInterface
{
@ -43,12 +46,12 @@ class CreditCard implements LivewireMethodInterface
private function getCustomer(): array
{
return [
$data = [
'first_name' => $this->powerboard->client->present()->first_name(),
'last_name' => $this->powerboard->client->present()->first_name(),
'email' => $this->powerboard->client->present()->email(),
'phone' => $this->powerboard->client->present()->phone(),
'type' => 'card',
// 'phone' => $this->powerboard->client->present()->phone(),
// 'type' => 'card',
'address_line1' => $this->powerboard->client->address1 ?? '',
'address_line2' => $this->powerboard->client->address2 ?? '',
'address_state' => $this->powerboard->client->state ?? '',
@ -56,8 +59,12 @@ class CreditCard implements LivewireMethodInterface
'address_city' => $this->powerboard->client->city ?? '',
'address_postcode' => $this->powerboard->client->postal_code ?? '',
];
return \App\Helpers\Sanitizer::removeBlanks($data);
}
private function storePaymentMethod($request)
private function storePaymentSource($request)
{
$this->powerboard->init();
@ -66,104 +73,24 @@ class CreditCard implements LivewireMethodInterface
$payload = array_merge($this->getCustomer(), [
'token' => $payment_source,
"vault_type" => "session",
'store_ccv' => true,
]);
$r = $this->powerboard->gatewayRequest('/v1/vault/payment_sources', (\App\Enum\HttpVerb::POST)->value, $payload, []);
// {
// "status": 201,
// "error": null,
// "resource": {
// "type": "payment_source",
// "data": {
// "type": "card",
// "_source_ip_address": "54.86.50.139",
// "expire_month": 1,
// "expire_year": 2023,
// "card_name": "John Citizen",
// "card_number_last4": "4242",
// "card_number_bin": "42424242",
// "card_scheme": "visa",
// "ref_token": "cus_hyyau7dpojJttR",
// "status": "active",
// "created_at": "2021-08-05T07:04:25.974Z",
// "company_id": "5d305bfbfac31b4448c738d7",
// "vault_token": "c90dbe45-7a23-4f26-9192-336a01e58e59",
// "updated_at": "2021-08-05T07:05:56.035Z"
// }
// }
// }
if($r->failed())
return $this->powerboard->processInternallyFailedPayment($this->powerboard, $r->throw());
nlog("payment source saving");
nlog($r->object());
$response_payload = $r->object();
$source = (new \App\PaymentDrivers\CBAPowerBoard\Models\Parse())->encode(PaymentSource ::class, $r->object()->resource->data);
nlog($response_payload);
return $source;
try {
// $cgt = $this->powerboard->customer()->storePaymentMethod(payment_source: $source, store_card: $request->store_card);
$payment_meta = new \stdClass();
$payment_meta->exp_month = (string) $response_payload->resource->data->expire_month;
$payment_meta->exp_year = (string) $response_payload->resource->data->expire_year;
$payment_meta->brand = (string) $response_payload->resource->data->card_scheme;
$payment_meta->last4 = (string) $response_payload->resource->data->card_number_last4;
$payment_meta->type = GatewayType::CREDIT_CARD;
$data = [
'payment_meta' => $payment_meta,
'token' => $response_payload->resource->data->vault_token,
'payment_method_id' => $request->payment_method_id,
];
//['gateway_customer_reference' => $response_payload->resource->data->ref_token]
$cgt = $this->powerboard->storeGatewayToken($data, []);
$customer_payload = [
'payment_source' => [
'vault_token' => $cgt->token,
'address_line1' => $this->powerboard->client->address1 ?? '',
'address_line2' => $this->powerboard->client->address1 ?? '',
'address_state' => $this->powerboard->client->state ?? '',
'address_country' => $this->powerboard->client->country->iso_3166_3 ?? '',
'address_city' => $this->powerboard->client->city ?? '',
'address_postcode' => $this->powerboard->client->postcode ?? '',
],
];
foreach ($customer_payload['payment_source'] as $key => $value) {
if (strlen($value ?? '') == 0) {
unset($customer_payload['payment_source'][$key]);
}
}
$customer = $this->powerboard->customer()->findOrCreateCustomer($customer_payload);
$cgt->gateway_customer_reference = $customer->_id;
$cgt->save();
//test that payment token is attached to customer here
$hit=false;
foreach($customer->payment_sources as $source){
if($source->vault_token == $cgt->token)
$hit = true;
}
if(!$hit)
$this->powerboard->customer()->addTokenToCustomer($cgt->token, $customer);
return $cgt;
} catch (\Exception $e) {
return $this->powerboard->processInternallyFailedPayment($this->powerboard, $e);
}
// return $cgt;
}
@ -198,137 +125,171 @@ class CreditCard implements LivewireMethodInterface
}
private function get3dsToken(PaymentSource $source, $request)
{
$payment_hash = PaymentHash::query()->where('hash', $request->payment_hash)->first();
$browser_details = json_decode($request->browser_details,true);
$payload = [
"amount" => $payment_hash->data->amount_with_fee,
"currency" => $this->powerboard->client->currency()->code,
"description" => $this->powerboard->getDescription(),
"customer" => [
"payment_source" => [
"vault_token" => $source->vault_token,
"gateway_id" => '66d65c5a68b7fa297a31c267',
],
],
"_3ds" => [
"browser_details" => $browser_details,
],
];
nlog($payload);
$r = $this->powerboard->gatewayRequest('/v1/charges/3ds', (\App\Enum\HttpVerb::POST)->value, $payload, []);
nlog($r->body());
if($r->failed())
$r->throw();
$charge = $r->json();
nlog($charge['resource']['data']);
return response()->json($charge['resource']['data'], 200);
}
public function paymentResponse(PaymentResponseRequest $request)
{
nlog($request->all());
$payment_hash = PaymentHash::where('hash', $request->payment_has)->first();
$token = $request->payment_source;
// $token = $request->payment_source;
$payload = [];
if($request->store_card) {
nlog("Store Payment Method");
$customer = $this->storePaymentMethod($request);
nlog($customer);
/** Token Payment */
if($request->input('token', false))
{
$cgt = $this->powerboard
->client
->gateway_tokens()
->where('company_gateway_id', $this->powerboard->company_gateway->id)
->where('token', $request->token)
->first();
$payload["customer"] = [
"payment_source" => [
"vault_token" => "c90dbe45-7a23-4f26-9192-336a01e58e59",
"gateway_id" => "5dde1f3799cfea21ed2fc942"
"vault_token" => $cgt->token,
"gateway_id" => $cgt->meta->gateway_id
]
];
}
elseif($request->browser_details)
{
$payment_source = $this->storePaymentSource($request);
return $this->get3dsToken($payment_source, $request);
}
elseif($request->charge) {
$payload = [
'3ds' => [
'id' => $request['charge']['charge_3ds_id'],
],
"amount"=> $payment_hash->data->amount_with_fee,
"currency"=> $this->powerboard->client->currency()->code,
"store_cvv"=> true,
];
$r = $this->powerboard->gatewayRequest("/v1/charges", (\App\Enum\HttpVerb::POST)->value, $payload, []);
if($r->failed())
$r->throw();
$charge = (new \App\PaymentDrivers\CBAPowerBoard\Models\Parse())->encode(Charge::class, $r->object()->resource->data) ?? $r->throw();
if ($charge->status == 'complete') {
$this->powerboard->logSuccessfulGatewayResponse(['response' => $charge, 'data' => $this->powerboard->payment_hash], SystemLog::TYPE_POWERBOARD);
return $this->processSuccessfulPayment($charge);
}
}
$uri = '/v1/charges';
$payload = [
"amount" => "10.00",
"currency" =>"AUD",
];
$r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::POST)->value, $payload, []);
// $payload = [
// 'amount' => $this->powerboard->payment_hash->amount_with_fee(),
// 'currency' => $this->powerboard->client->currency()->code,
// 'description' => $this->powerboard->getDescription(),
// // 'descriptor' => ,
// // 'reference' => ,
// // 'reference2' => ,
// // 'amount_surcharge' => ,
// // 'amount_original' => ,
// // 'initialization_source' => ,
// 'bypass_3ds' => false,
// // 'token'=> ,
// 'payment_source_id' => $request->payment_source,
// // 'customer_id' => ,
// 'customer' => $this->getCustomer(),
// ];
nlog($request->all());
// $this->stripe->init();
// $state = [
// 'server_response' => json_decode($request->gateway_response),
// 'payment_hash' => $request->payment_hash,
// ];
// $state = array_merge($state, $request->all());
// $state['store_card'] = boolval($state['store_card']);
// if ($request->has('token') && ! is_null($request->token)) {
// $state['store_card'] = false;
// else {
// $payload["customer"] = [
// "payment_source" => [
// "vault_token" => $cgt->token,
// "gateway_id" => $cgt->meta->gateway_id
// ]
// ];
// }
// $state['payment_intent'] = PaymentIntent::retrieve($state['server_response']->id, array_merge($this->stripe->stripe_connect_auth, ['idempotency_key' => uniqid("st", true)]));
// $state['customer'] = $state['payment_intent']->customer;
// $uri = '/v1/charges';
// $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, $state);
// $this->stripe->payment_hash->save();
// $payload_meta = [
// "amount" => $payment_hash->data->amount_with_fee,
// "currency" => $this->powerboard->client->currency()->code,
// "description" => $this->powerboard->getDescription(),
// ];
// $server_response = $this->stripe->payment_hash->data->server_response;
// $payload = array_merge($payload, $payload_meta);
// nlog($payload);
// if ($server_response->status == 'succeeded') {
// $this->stripe->logSuccessfulGatewayResponse(['response' => json_decode($request->gateway_response), 'data' => $this->stripe->payment_hash], SystemLog::TYPE_STRIPE);
// $r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::POST)->value, $payload, []);
// return $this->processSuccessfulPayment();
// }
// if($r->failed())
// $r->throw();
// return $this->processUnsuccessfulPayment($server_response);
// nlog($r->object());
// return $this->processUnsuccessfulPayment($r->body());
}
public function processSuccessfulPayment()
public function processSuccessfulPayment(Charge $charge)
{
// UpdateCustomer::dispatch($this->stripe->company_gateway->company->company_key, $this->stripe->company_gateway->id, $this->stripe->client->id);
// $stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method);
$data = [
'payment_type' => PaymentType::CREDIT_CARD_OTHER,
'amount' => $this->powerboard->payment_hash->data->amount_with_fee,
'transaction_reference' => $charge->_id,
'gateway_type_id' => GatewayType::CREDIT_CARD,
];
// $data = [
// 'payment_method' => $this->stripe->payment_hash->data->server_response->payment_method,
// 'payment_type' => PaymentType::parseCardType(strtolower($stripe_method->card->brand)) ?: PaymentType::CREDIT_CARD_OTHER,
// 'amount' => $this->stripe->convertFromStripeAmount($this->stripe->payment_hash->data->server_response->amount, $this->stripe->client->currency()->precision, $this->stripe->client->currency()),
// 'transaction_reference' => isset($this->stripe->payment_hash->data->payment_intent->latest_charge) ? $this->stripe->payment_hash->data->payment_intent->latest_charge : optional($this->stripe->payment_hash->data->payment_intent->charges->data[0])->id,
// 'gateway_type_id' => GatewayType::CREDIT_CARD,
// ];
$payment = $this->powerboard->createPayment($data, Payment::STATUS_COMPLETED);
// $this->stripe->payment_hash->data = array_merge((array) $this->stripe->payment_hash->data, ['amount' => $data['amount']]);
// $this->stripe->payment_hash->save();
SystemLogger::dispatch(
['response' => $this->powerboard->payment_hash->data->server_response, 'data' => $data],
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_POWERBOARD,
$this->powerboard->client,
$this->powerboard->client->company,
);
// if ($this->stripe->payment_hash->data->store_card) {
// $customer = new \stdClass();
// $customer->id = $this->stripe->payment_hash->data->customer;
if ($payment->invoices()->whereHas('subscription')->exists()) {
$subscription = $payment->invoices()->first()->subscription;
// $this->stripe->attach($this->stripe->payment_hash->data->server_response->payment_method, $customer);
if ($subscription && array_key_exists('return_url', $subscription->webhook_configuration) && strlen($subscription->webhook_configuration['return_url']) >= 1) {
return redirect($subscription->webhook_configuration['return_url']);
}
}
// $stripe_method = $this->stripe->getStripePaymentMethod($this->stripe->payment_hash->data->server_response->payment_method);
// $this->storePaymentMethod($stripe_method, $this->stripe->payment_hash->data->payment_method_id, $customer);
// }
// $payment = $this->stripe->createPayment($data, Payment::STATUS_COMPLETED);
// SystemLogger::dispatch(
// ['response' => $this->stripe->payment_hash->data->server_response, 'data' => $data],
// SystemLog::CATEGORY_GATEWAY_RESPONSE,
// SystemLog::EVENT_GATEWAY_SUCCESS,
// SystemLog::TYPE_STRIPE,
// $this->stripe->client,
// $this->stripe->client->company,
// );
// if ($payment->invoices()->whereHas('subscription')->exists()) {
// $subscription = $payment->invoices()->first()->subscription;
// if ($subscription && array_key_exists('return_url', $subscription->webhook_configuration) && strlen($subscription->webhook_configuration['return_url']) >= 1) {
// return redirect($subscription->webhook_configuration['return_url']);
// }
// }
// return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
return redirect()->route('client.payments.show', ['payment' => $payment->hashed_id]);
}
public function processUnsuccessfulPayment($server_response)

View File

@ -12,8 +12,10 @@
namespace App\PaymentDrivers\CBAPowerBoard;
use App\Helpers\Sanitizer;
use App\Models\ClientGatewayToken;
use App\PaymentDrivers\CBAPowerBoard\Models\Customer as ModelsCustomer;
use App\PaymentDrivers\CBAPowerBoard\Models\PaymentSource;
use App\PaymentDrivers\CBAPowerBoardPaymentDriver;
class Customer
@ -49,10 +51,11 @@ class Customer
$r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::GET)->value, [], []);
nlog($r->json());
if($r->successful())
return $r->object();
return false;
}
@ -68,6 +71,8 @@ class Customer
$search_results = $r->object();
nlog($search_results);
$customers = $search_results->resource->data;
return reset($customers); // returns first element or false
@ -83,17 +88,13 @@ class Customer
'last_name' => $this->powerboard->client->present()->first_name(),
'email' => $this->powerboard->client->present()->email(),
'reference' => $this->powerboard->client->client_hash,
'phone' => $this->powerboard->client->present()->phone(),
// 'phone' => $this->powerboard->client->present()->phone(),
];
foreach($payload as $key => $value){
if(strlen($value ?? '') == 0)
unset($payload[$key]);
}
$payload = array_merge($payload, $data);
$payload = Sanitizer::removeBlanks($payload);
nlog($payload);
@ -101,25 +102,29 @@ class Customer
$r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::POST)->value, $payload, []);
if($r->successful())
$this->storePaymentMethod($r->object());
if($r->failed())
$r->throw();
// $this->storePaymentMethod($r->object());
return (new \App\PaymentDrivers\CBAPowerBoard\Models\Parse())->encode(ModelsCustomer::class, $r->object()->resource->data) ?? $r->throw();
}
private function storePaymentMethod(mixed $customer): ClientGatewayToken
public function storePaymentMethod(?PaymentSource $payment_source = null, ?ModelsCustomer $customer = null, bool $store_card = false): ClientGatewayToken
{
$response_payload = $customer->resource->data;
$source = end($customer->resource->data->payment_sources);
// $response_payload = $customer->resource->data;
// $source = end($customer->resource->data->payment_sources);
/** @var PaymentSource $source */
$source = $payment_source ? $payment_source : end($customer->payment_sources);
$payment_meta = new \stdClass();
$payment_meta->exp_month = (string) $source->expire_month;
$payment_meta->exp_year = (string) $source->expire_year;
$payment_meta->brand = (string) $source->card_scheme;
$payment_meta->last4 = (string) $source->card_number_last4;
$payment_meta->gateway_id = (string) $source->gateway_id;
$payment_meta->gateway_id = is_null($source->gateway_id) ? (string) $source->gateway_id : false;
$payment_meta->type = \App\Models\GatewayType::CREDIT_CARD;
$data = [
@ -128,16 +133,37 @@ class Customer
'payment_method_id' => \App\Models\GatewayType::CREDIT_CARD,
];
$cgt = $this->powerboard->storeGatewayToken($data, ['gateway_customer_reference' => $response_payload->_id]);
$additional_data = $customer ? ['gateway_customer_reference' => $customer->_id] : [];
$cgt = $this->powerboard->storeGatewayToken($data, $additional_data);
return $cgt;
if($customer || !$store_card)
return $cgt;
$customer_payload = [
'payment_source' => [
'vault_token' => $cgt->token,
'address_line1' => $this->powerboard->client->address1 ?? '',
'address_line2' => $this->powerboard->client->address1 ?? '',
'address_state' => $this->powerboard->client->state ?? '',
'address_country' => $this->powerboard->client->country->iso_3166_3 ?? '',
'address_city' => $this->powerboard->client->city ?? '',
'address_postcode' => $this->powerboard->client->postcode ?? '',
],
];
$customer = $this->findOrCreateCustomer($customer_payload);
$this->addTokenToCustomer($cgt->token, $customer);
return $cgt->fresh();
}
public function addTokenToCustomer(string $token, mixed $customer): mixed
public function addTokenToCustomer(string $token, ModelsCustomer $customer): mixed
{
nlog("add token to customer");
$uri = "/v1/customers/{$customer->_id}";
$payload = [
@ -148,7 +174,36 @@ class Customer
$r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::POST)->value, $payload, []);
return $r->successful() ? $r->object() : $r->throw();
if($r->failed()){
nlog($r->body());
return $r->throw();
}
nlog($r->object());
$customer = (new \App\PaymentDrivers\CBAPowerBoard\Models\Parse())->encode(ModelsCustomer::class, $r->object()->resource->data);
$source = collect($customer->payment_sources)->first(function (PaymentSource $source) use ($token){
return $token == $source->vault_token;
});
nlog("i found the source");
nlog($source);
$cgt = $this->powerboard
->client
->gateway_tokens()
->where('token', $token)
->first();
nlog($cgt->id);
$meta = $cgt->meta;
$meta->gateway_id = $source->gateway_id;
$cgt->meta = $meta;
$cgt->save();
return $r->object();
}
}

View File

@ -0,0 +1,87 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\CBAPowerBoard\Models;
class Charge
{
/** @var string */
public string $external_id;
/** @var string */
public string $_id;
/** @var string */
public string $created_at;
/** @var string */
public string $updated_at;
/** @var string */
public string $remittance_date;
/** @var string */
public string $company_id;
/** @var int */
public int $amount;
/** @var string */
public string $currency;
/** @var int */
public int $__v;
/** @var Transactions[] */
public array $transactions;
/** @var bool */
public bool $one_off;
/** @var bool */
public bool $archived;
/** @var Customer */
public Customer $customer;
/** @var bool */
public bool $capture;
/** @var string */
public string $status;
/** @var array */
public array $items;
/**
* @param Transactions[] $transactions
*/
public function __construct(
string $external_id,
string $_id,
string $created_at,
string $updated_at,
string $remittance_date,
string $company_id,
int $amount,
string $currency,
int $__v,
array $transactions,
bool $one_off,
bool $archived,
Customer $customer,
bool $capture,
string $status,
array $items,
) {
$this->external_id = $external_id;
$this->_id = $_id;
$this->created_at = $created_at;
$this->updated_at = $updated_at;
$this->remittance_date = $remittance_date;
$this->company_id = $company_id;
$this->amount = $amount;
$this->currency = $currency;
$this->__v = $__v;
$this->transactions = $transactions;
$this->one_off = $one_off;
$this->archived = $archived;
$this->customer = $customer;
$this->capture = $capture;
$this->status = $status;
$this->items = $items;
}
}

View File

@ -38,7 +38,7 @@ class Customer
public string $updated_at;
/** @var bool */
public bool $_check_expire_date;
/** @var PaymentSources[] */
/** @var PaymentSource[] */
public array $payment_sources;
/** @var array */
public array $payment_destinations;
@ -46,7 +46,7 @@ class Customer
public string $company_id;
/**
* @param PaymentSources[] $payment_sources
* @param PaymentSource[] $payment_sources
*/
public function __construct(
string $_id,

View File

@ -0,0 +1,96 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\CBAPowerBoard\Models;
class PaymentSource
{
/** @var ?string */
public ?string $_id;
/** @var string */
public string $type;
/** @var string */
public string $vault_token;
/** @var string */
public string $card_name;
/** @var string */
public string $card_number_bin;
/** @var string */
public string $card_number_last4;
/** @var string */
public string $card_scheme;
/** @var string|null */
public ?string $address_line1;
/** @var string|null */
public ?string $address_line2;
/** @var string|null */
public ?string $address_city;
/** @var string|null */
public ?string $address_country;
/** @var string|null */
public ?string $address_state;
/** @var int */
public int $expire_month;
/** @var int */
public int $expire_year;
/** @var string */
public string $status;
/** @var string */
public string $created_at;
/** @var string */
public string $updated_at;
/** @var string */
public string $vault_type;
/** @var ?string */
public ?string $gateway_id;
public function __construct(
?string $_id,
string $type,
string $vault_token,
string $card_name,
string $card_number_bin,
string $card_number_last4,
string $card_scheme,
?string $address_line1,
?string $address_line2,
?string $address_city,
?string $address_country,
?string $address_state,
int $expire_month,
int $expire_year,
string $status,
string $created_at,
string $updated_at,
string $vault_type,
?string $gateway_id
) {
$this->_id = $_id;
$this->type = $type;
$this->vault_token = $vault_token;
$this->card_name = $card_name;
$this->card_number_bin = $card_number_bin;
$this->card_number_last4 = $card_number_last4;
$this->card_scheme = $card_scheme;
$this->address_line1 = $address_line1;
$this->address_line2 = $address_line2;
$this->address_city = $address_city;
$this->address_country = $address_country;
$this->address_state = $address_state;
$this->expire_month = $expire_month;
$this->expire_year = $expire_year;
$this->status = $status;
$this->created_at = $created_at;
$this->updated_at = $updated_at;
$this->vault_type = $vault_type;
$this->gateway_id = $gateway_id;
}
}

View File

@ -13,80 +13,6 @@ namespace App\PaymentDrivers\CBAPowerBoard\Models;
class PaymentSources
{
/** @var string */
public string $_id;
/** @var string */
public string $type;
/** @var string */
public string $vault_token;
/** @var string */
public string $card_name;
/** @var string */
public string $card_number_bin;
/** @var string */
public string $card_number_last4;
/** @var string */
public string $card_scheme;
/** @var string|null */
public ?string $address_line1;
/** @var string|null */
public ?string $address_line2;
/** @var string|null */
public ?string $address_city;
/** @var string|null */
public ?string $address_country;
/** @var string|null */
public ?string $address_state;
/** @var int */
public int $expire_month;
/** @var int */
public int $expire_year;
/** @var string */
public string $status;
/** @var string */
public string $created_at;
/** @var string */
public string $updated_at;
/** @var string */
public string $vault_type;
public function __construct(
string $_id,
string $type,
string $vault_token,
string $card_name,
string $card_number_bin,
string $card_number_last4,
string $card_scheme,
?string $address_line1,
?string $address_line2,
?string $address_city,
?string $address_country,
?string $address_state,
int $expire_month,
int $expire_year,
string $status,
string $created_at,
string $updated_at,
string $vault_type
) {
$this->_id = $_id;
$this->type = $type;
$this->vault_token = $vault_token;
$this->card_name = $card_name;
$this->card_number_bin = $card_number_bin;
$this->card_number_last4 = $card_number_last4;
$this->card_scheme = $card_scheme;
$this->address_line1 = $address_line1;
$this->address_line2 = $address_line2;
$this->address_city = $address_city;
$this->address_country = $address_country;
$this->address_state = $address_state;
$this->expire_month = $expire_month;
$this->expire_year = $expire_year;
$this->status = $status;
$this->created_at = $created_at;
$this->updated_at = $updated_at;
$this->vault_type = $vault_type;
}
/** @var \App\PaymentDrivers\CBAPowerBoard\Models\PaymentSources[] */
public array $payment_sources;
}

View File

@ -0,0 +1,64 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\PaymentDrivers\CBAPowerBoard\Models;
class Transactions
{
/** @var string */
public string $created_at;
/** @var int */
public int $amount;
/** @var string */
public string $currency;
/** @var string */
public string $_id;
/** @var string */
public ?string $error_code;
/** @var ?string */
public ?string $error_message;
/** @var ?string */
public ?string $gateway_specific_description;
/** @var ?string */
public ?string $gateway_specific_code;
/** @var string */
public string $_source_ip_address;
/** @var string */
public string $status;
/** @var string */
public string $type;
public function __construct(
string $created_at,
int $amount,
string $currency,
string $_id,
?string $error_code,
?string $error_message,
?string $gateway_specific_description,
?string $gateway_specific_code,
string $_source_ip_address,
string $status,
string $type
) {
$this->created_at = $created_at;
$this->amount = $amount;
$this->currency = $currency;
$this->_id = $_id;
$this->error_code = $error_code;
$this->error_message = $error_message;
$this->gateway_specific_description = $gateway_specific_description;
$this->gateway_specific_code = $gateway_specific_code;
$this->_source_ip_address = $_source_ip_address;
$this->status = $status;
$this->type = $type;
}
}

View File

@ -93,7 +93,7 @@ inset: 6px;
document.getElementById("gateway_response").value =JSON.stringify( data );
formData = JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server_response")))),
fetch('{{ route('client.payments.response') }}', {
method: 'POST',
headers: {

View File

@ -16,6 +16,8 @@
<input type="hidden" name="payment_method_id" value="{{ $payment_method_id }}">
<input type="hidden" name="token">
<input type="hidden" name="browser_details">
<input type="hidden" name="charge">
<button type="submit" class="hidden" id="stub">Submit</button>
</form>
@ -63,6 +65,7 @@
<div id="powerboard-payment-container" class="w-full">
<div id="widget" style="block"></div>
</div>
@include('portal.ninja2020.gateways.includes.save_card')
@include('portal.ninja2020.gateways.includes.pay_now')
@ -84,7 +87,7 @@
var widget = new cba.HtmlWidget('#widget', '{{ $public_key }}', 'not_configured');
widget.setEnv("{{ $environment }}");
widget.useAutoResize();
widget.interceptSubmitForm('#server-response');
// widget.interceptSubmitForm('#server-response');
widget.onFinishInsert('input[name="gateway_response"]', "payment_source");
widget.load();
@ -131,30 +134,69 @@
widget.on("validationError", function(data) {
console.log("validationError", data);
});
widget.on("finish", async function(data) {
widget.on("finish", function(data) {
console.log("finish", data);
try {
const resource = await get3dsToken();
console.log("3DS Token:", resource);
console.log("pre canvas");
var canvas = new cba.Canvas3ds('#widget-3dsecure', resource._3ds.token);
canvas.load();
console.log("post canvas");
canvas.on("chargeAuthSuccess", function(data) {
console.log(data);
document.querySelector(
'input[name="browser_details"]'
).value = null;
document.querySelector(
'input[name="charge"]'
).value = JSON.stringify(data);
document.getElementById('server-response').submit();
});
canvas.on("chargeAuthReject", function(data) {
console.log(data);
});
} catch (error) {
console.error("Error fetching 3DS Token:", error);
}
});
widget.on('form_submit', function (data) {
console.log("form_submit", data);
widget.on("submit", async function (data){
console.log("submit");
console.log(data);
})
widget.on('form_submit', function (data) {
console.log("form_submit", data);
console.log(data);
});
widget.on('submit', function (data) {
console.log("submit", data);
console.log(data);
});
widget.on('tab', function (data) {
console.log("tab", data);
console.log(data);
});
@ -185,6 +227,53 @@
});
async function get3dsToken() {
const browserDetails = {
name: navigator.userAgent.substring(0, 100), // The full user agent string, which contains the browser name and version
java_enabled: navigator.javaEnabled() ? "true" : "false", // Indicates if Java is enabled in the browser
language: navigator.language || navigator.userLanguage, // The browser language
screen_height: window.screen.height.toString(), // Screen height in pixels
screen_width: window.screen.width.toString(), // Screen width in pixels
time_zone: (new Date().getTimezoneOffset() * -1).toString(), // Timezone offset in minutes (negative for behind UTC)
color_depth: window.screen.colorDepth.toString() // Color depth in bits per pixel
};
document.querySelector(
'input[name="browser_details"]'
).value = JSON.stringify(browserDetails);
const formData = JSON.stringify(Object.fromEntries(new FormData(document.getElementById("server-response"))));
try {
// Return the fetch promise to handle it externally
const response = await fetch('{{ route('client.payments.response') }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
},
body: formData
})
if (!response.ok) {
const text = await response.text();
throw new Error(`Network response was not ok: ${response.statusText}. Response text: ${text}`);
}
return await response.json()
}
catch(error) {
console.error('Fetch error:', error); // Log error for debugging
throw error; //
}
}
</script>
@endsection