powerboard

This commit is contained in:
David Bomba 2024-09-07 09:34:53 +10:00
parent 67407103c7
commit 6d2638c603
5 changed files with 312 additions and 21 deletions

22
app/Enum/HttpVerb.php Normal file
View File

@ -0,0 +1,22 @@
<?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\Enum;
enum HttpVerb: string
{
case POST = 'post';
case PUT = 'put';
case GET = 'get';
case PATCH = 'patch';
case DELETE = 'delete';
}

View File

@ -64,12 +64,18 @@ class CreditCard implements LivewireMethodInterface
$payment_source = $request->gateway_response; $payment_source = $request->gateway_response;
$payload = [ $customer = $this->powerboard->customer()->findOrCreateCustomer($payment_source);
nlog($customer);
$payload = array_merge($this->getCustomer(), [
'token' => $payment_source, 'token' => $payment_source,
'store_ccv' => true, 'store_ccv' => true,
]; ]);
$r = $this->powerboard->gatewayRequest('/v1/vault/payment_sources', (\App\Enum\HttpVerb::POST)->value, array_merge($this->getCustomer(), $payload), []); nlog($payload);
$r = $this->powerboard->gatewayRequest('/v1/vault/payment_sources', (\App\Enum\HttpVerb::POST)->value, $payload, []);
// { // {
// "status": 201, // "status": 201,
@ -116,7 +122,8 @@ class CreditCard implements LivewireMethodInterface
'payment_method_id' => $request->payment_method_id, 'payment_method_id' => $request->payment_method_id,
]; ];
$cgt = $this->powerboard->storeGatewayToken($data, ['gateway_customer_reference' => $response_payload->resource->data->ref_token]); //['gateway_customer_reference' => $response_payload->resource->data->ref_token]
$cgt = $this->powerboard->storeGatewayToken($data, []);
return $cgt; return $cgt;

View File

@ -0,0 +1,215 @@
<?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;
use App\Models\ClientGatewayToken;
use App\PaymentDrivers\CBAPowerBoardPaymentDriver;
class Customer
{
public function __construct(public CBAPowerBoardPaymentDriver $powerboard)
{
}
public function findOrCreateCustomer(string $payment_source): mixed
{
$token = $this->powerboard
->client
->gateway_tokens()
->where('company_gateway_id', $this->powerboard->company_gateway->id)
->first();
if($token && $customer = $this->getCustomer($token->gateway_customer_reference)){
return $customer;
}
if($customer = $this->findCustomer())
return $customer;
return $this->createCustomer(['token' => $payment_source]);
}
public function getCustomer(string $id): mixed
{
$uri = "/v1/customers/{$id}";
$r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::GET)->value, [], []);
if($r->successful())
return $r->object();
return false;
}
public function findCustomer(): mixed
{
$uri = '/v1/customers';
$query = [
'reference' => $this->powerboard->client->client_hash,
];
$r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::GET)->value, $query, []);
$search_results = $r->object();
return reset($search_results->resource->data); // returns first element or false
}
/*
token +2 string(UIID) One-time token with all the payment source information
reference - string Manually defined reference for customer in payment systems
description - string Customer description. This is customer internal description
company_name - string Customer company name
first_name - string Customer first name
last_name - string Customer last name
email - string Customer email
phone - string(E.164) Customer phone in E.164 international notation (Example: +12345678901)
default_source + string (24 hex characters) Payment source used by default
payment_source + object Object with payment information
payment_source.gateway_id -4 string (24 hex characters) Gateway id
payment_source.vault_token +3 string (UIID) Vault token
payment_source.type + string Type of payment. card for payment with credit card
payment_source.card_name +1 string Cardholder name (as on card)
payment_source.card_number +1 string(numeric) Card number
payment_source.expire_month +1 string(mm) Card expiration month mm
payment_source.expire_year +1 string(yyyy) Card expiration year
payment_source.card_ccv -1 string(numeric) Card CCV number
payment_source.address_line1 - string Customer Address, line 1
payment_source.address_line2 - string Customer Address, line 2
payment_source.address_state - string Customer Address, State
payment_source.address_country - string Customer Address, Country Code
payment_source.address_city - string Customer Address, City
payment_source.address_postcode
*/
public function createCustomer(array $data = []): object
{
// 'address_line1' => $this->powerboard->client->address1 ?? '',
// 'address_line2' => $this->powerboard->client->address2 ?? '',
// '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->postal_code ?? '',
$payload = [
'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(),
'reference' => $this->powerboard->client->client_hash,
];
$payload = array_merge($payload, $data);
$uri = "/v1/customers";
$r = $this->powerboard->gatewayRequest($uri, (\App\Enum\HttpVerb::POST)->value, $payload, []);
if($r->successful())
$this->storePaymentMethod($r->object());
return $r->object() ?? $r->throw();
}
/*
{
"status": 201,
"error": null,
"resource": {
"type": "customer",
"data": {
"statistics": {
"successful_transactions": 0,
"total_collected_amount": 0
},
"_check_expire_date": false,
"archived": false,
"_source_ip_address": "130.41.62.108",
"_id": "64b09a3d1e04e51be27f16c5",
"company_id": "63cf32a154a870183bf2398a",
"email": "john@test.com",
"first_name": "John",
"last_name": "Customer",
"phone": "+61111111111",
"reference": "Customer 1",
"default_source": "64b09a341e04e51be27f16c2",
"_service": {
"default_gateway_id": "63cf37b142194166721498e9"
},
"payment_sources": [
{
"type": "card",
"_id": "64b09a341e04e51be27f16c2",
"expire_month": 1,
"expire_year": 2039,
"card_name": "John Customer",
"card_scheme": "mastercard",
"card_number_last4": "1118",
"card_number_bin": "51111111",
"ref_token": "9191664642213170",
"status": "active",
"created_at": "2023-07-14T00:43:32.375Z",
"gateway_id": "63cf37b142194166721498e9",
"gateway_type": "MasterCard",
"gateway_name": "CommWeb",
"vault_token": "b944dfb0-35f4-47d6-a306-2b79cebf34f3",
"updated_at": "2023-07-14T00:43:41.169Z"
}
],
"payment_destinations": [],
"updated_at": "2023-07-14T00:43:41.170Z",
"created_at": "2023-07-14T00:43:41.170Z",
"__v": 0
}
}
}
*/
private function storePaymentMethod(mixed $customer): ClientGatewayToken
{
$response_payload = $customer->resource->data;
$source = end($customer->resource->data->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->type = \App\Models\GatewayType::CREDIT_CARD;
$data = [
'payment_meta' => $payment_meta,
'token' => $source->vault_token,
'payment_method_id' => \App\Models\GatewayType::CREDIT_CARD,
];
$cgt = $this->powerboard->storeGatewayToken($data, ['gateway_customer_reference' => $response_payload->_id]);
return $cgt;
}
// public function updateCustomer(string $id, $data): object
// {
// }
}

View File

@ -24,6 +24,7 @@ use App\Utils\Traits\MakesHash;
use App\Models\ClientGatewayToken; use App\Models\ClientGatewayToken;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use App\PaymentDrivers\CBAPowerBoard\CreditCard; use App\PaymentDrivers\CBAPowerBoard\CreditCard;
use App\PaymentDrivers\CBAPowerBoard\Customer;
/** /**
* Class CBAPowerBoardPaymentDriver. * Class CBAPowerBoardPaymentDriver.
@ -44,6 +45,8 @@ class CBAPowerBoardPaymentDriver extends BaseDriver
public string $environment = 'production_cba'; public string $environment = 'production_cba';
public const SYSTEM_LOG_TYPE = SystemLog::TYPE_POWERBOARD;
public static $methods = [ public static $methods = [
GatewayType::CREDIT_CARD => CreditCard::class, GatewayType::CREDIT_CARD => CreditCard::class,
]; ];
@ -156,8 +159,14 @@ class CBAPowerBoardPaymentDriver extends BaseDriver
public function gatewayRequest(string $uri, string $verb, array $payload, array $headers = []) public function gatewayRequest(string $uri, string $verb, array $payload, array $headers = [])
{ {
$this->init();
$r = Http::withHeaders($this->getHeaders($headers)) $r = Http::withHeaders($this->getHeaders($headers))
->{$verb}($this->api_endpoint.$uri, $payload); ->{$verb}($this->api_endpoint.$uri, $payload);
nlog($r->body());
return $r;
} }
public function getHeaders(array $headers = []): array public function getHeaders(array $headers = []): array
@ -169,4 +178,8 @@ class CBAPowerBoardPaymentDriver extends BaseDriver
$headers); $headers);
} }
public function customer(): Customer
{
return new Customer($this);
}
} }

View File

@ -88,39 +88,73 @@
widget.onFinishInsert('input[name="gateway_response"]', "payment_source"); widget.onFinishInsert('input[name="gateway_response"]', "payment_source");
widget.load(); widget.load();
widget.on("systemError", function(data) { widget.trigger('tab', function (data){
console.log("Widget Response", data);
// document.querySelector( console.log("tab Response", data);
// 'input[name="gateway_response"]'
// ).value = JSON.stringify(data); console.log(widget.isValidForm());
let payNow = document.getElementById('pay-now');
payNow.disabled = widget.isInvalidForm();
}); });
widget.trigger('submit_form',function (data){
console.log("submit_form Response", data);
console.log(widget.isValidForm());
let payNow = document.getElementById('pay-now');
payNow.disabled = widget.isInvalidForm();
});
widget.trigger('tab',function (data){
console.log("tab Response", data);
console.log(widget.isValidForm());
let payNow = document.getElementById('pay-now');
payNow.disabled = widget.isInvalidForm();
});
widget.on("systemError", function(data) {
console.log("systemError Response", data);
});
widget.on("validationError", function(data) { widget.on("validationError", function(data) {
console.log("Widget Response", data); console.log("validationError", data);
// document.querySelector(
// 'input[name="gateway_response"]'
// ).value = JSON.stringify(data);
}); });
widget.on("finish", function(data) { widget.on("finish", function(data) {
console.log("Widget Response", data); console.log("finish", data);
// document.querySelector(
// 'input[name="gateway_response"]'
// ).value = JSON.stringify(data);
}); });
widget.on('form_submit', function (data) { widget.on('form_submit', function (data) {
console.log("form_submit", data);
console.log(data); console.log(data);
}); });
widget.on('submit', function (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); console.log(data);
}); });