From 0033fee578d5b2e06cc87a59acbb52ed3516eb07 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 12:05:19 +1100 Subject: [PATCH 01/42] Paypal --- app/Console/Commands/CreateSingleAccount.php | 103 ++++-- .../Controllers/CompanyGatewayController.php | 38 +- .../StoreCompanyGatewayRequest.php | 7 +- .../UpdateCompanyGatewayRequest.php | 5 +- app/Models/CompanyGateway.php | 3 +- app/Models/Gateway.php | 16 +- app/Models/SystemLog.php | 2 + app/PaymentDrivers/BaseDriver.php | 5 + .../PayPalPPCPPaymentDriver.php | 342 ++++++++++++++++++ app/PaymentDrivers/StripePaymentDriver.php | 2 +- config/ninja.php | 5 + .../2023_10_15_204204_add_paypal_ppcp.php | 49 +++ database/seeders/PaymentLibrariesSeeder.php | 8 +- .../build/assets/eway-credit-card-62ce5f3b.js | 9 + 14 files changed, 532 insertions(+), 62 deletions(-) create mode 100644 app/PaymentDrivers/PayPalPPCPPaymentDriver.php create mode 100644 database/migrations/2023_10_15_204204_add_paypal_ppcp.php create mode 100644 public/build/assets/eway-credit-card-62ce5f3b.js diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index a28eb64e23..1c6867f9d7 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -11,51 +11,52 @@ namespace App\Console\Commands; -use App\DataMapper\ClientRegistrationFields; -use App\DataMapper\CompanySettings; -use App\DataMapper\FeesAndLimits; -use App\Events\Invoice\InvoiceWasCreated; -use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; -use App\Factory\GroupSettingFactory; -use App\Factory\InvoiceFactory; -use App\Factory\InvoiceItemFactory; -use App\Factory\RecurringInvoiceFactory; -use App\Factory\SubscriptionFactory; -use App\Helpers\Invoice\InvoiceSum; -use App\Jobs\Company\CreateCompanyTaskStatuses; -use App\Libraries\MultiDB; -use App\Models\Account; -use App\Models\BankIntegration; -use App\Models\BankTransaction; -use App\Models\BankTransactionRule; -use App\Models\Client; -use App\Models\ClientContact; -use App\Models\Company; -use App\Models\CompanyGateway; -use App\Models\CompanyToken; -use App\Models\Country; -use App\Models\Credit; -use App\Models\Expense; -use App\Models\Product; -use App\Models\Project; -use App\Models\Quote; -use App\Models\RecurringInvoice; -use App\Models\Task; -use App\Models\TaxRate; -use App\Models\User; -use App\Models\Vendor; -use App\Models\VendorContact; -use App\Repositories\InvoiceRepository; -use App\Utils\Ninja; -use App\Utils\Traits\GeneratesCounter; -use App\Utils\Traits\MakesHash; +use stdClass; use Carbon\Carbon; use Faker\Factory; +use App\Models\Task; +use App\Models\User; +use App\Utils\Ninja; +use App\Models\Quote; +use App\Models\Client; +use App\Models\Credit; +use App\Models\Vendor; +use App\Models\Account; +use App\Models\Company; +use App\Models\Country; +use App\Models\Expense; +use App\Models\Gateway; +use App\Models\Product; +use App\Models\Project; +use App\Models\TaxRate; +use App\Libraries\MultiDB; +use App\Models\CompanyToken; +use App\Models\ClientContact; +use App\Models\VendorContact; +use App\Models\CompanyGateway; +use App\Factory\InvoiceFactory; +use App\Models\BankIntegration; +use App\Models\BankTransaction; +use App\Utils\Traits\MakesHash; use Illuminate\Console\Command; -use Illuminate\Support\Facades\Cache; +use App\Models\RecurringInvoice; +use App\DataMapper\FeesAndLimits; +use App\DataMapper\CompanySettings; +use App\Factory\InvoiceItemFactory; +use App\Helpers\Invoice\InvoiceSum; +use App\Models\BankTransactionRule; +use App\Factory\GroupSettingFactory; +use App\Factory\SubscriptionFactory; use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Facades\Cache; +use App\Utils\Traits\GeneratesCounter; use Illuminate\Support\Facades\Schema; -use stdClass; +use App\Repositories\InvoiceRepository; +use App\Factory\RecurringInvoiceFactory; +use App\Events\Invoice\InvoiceWasCreated; +use App\DataMapper\ClientRegistrationFields; +use App\Jobs\Company\CreateCompanyTaskStatuses; +use App\Events\RecurringInvoice\RecurringInvoiceWasCreated; class CreateSingleAccount extends Command { @@ -883,6 +884,28 @@ class CreateSingleAccount extends Command $cg->fees_and_limits = $fees_and_limits; $cg->save(); } + + if (config('ninja.testvars.ppcp') && ($this->gateway == 'all' || $this->gateway == 'square')) { + $cg = new CompanyGateway; + $cg->company_id = $company->id; + $cg->user_id = $user->id; + $cg->gateway_key = '80af24a6a691230bbec33e930ab40666'; + $cg->require_cvv = true; + $cg->require_billing_address = true; + $cg->require_shipping_address = true; + $cg->update_details = true; + $cg->config = encrypt(config('ninja.testvars.ppcp')); + $cg->save(); + + $fees_and_limits = new stdClass; + // $fees_and_limits->{$gateway_types[0]} = new FeesAndLimits; + $fees_and_limits->{3} = new FeesAndLimits; + + $cg->fees_and_limits = $fees_and_limits; + $cg->save(); + + } + } private function createRecurringInvoice($client) diff --git a/app/Http/Controllers/CompanyGatewayController.php b/app/Http/Controllers/CompanyGatewayController.php index 5e9fed6bfd..41eb81d445 100644 --- a/app/Http/Controllers/CompanyGatewayController.php +++ b/app/Http/Controllers/CompanyGatewayController.php @@ -194,21 +194,27 @@ class CompanyGatewayController extends BaseController */ public function store(StoreCompanyGatewayRequest $request) { - $company_gateway = CompanyGatewayFactory::create(auth()->user()->company()->id, auth()->user()->id); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + $company_gateway = CompanyGatewayFactory::create($user->company()->id, $user->id); $company_gateway->fill($request->all()); $company_gateway->save(); - /*Always ensure at least one fees and limits object is set per gateway*/ - if (! isset($company_gateway->fees_and_limits)) { - $gateway_types = $company_gateway->driver(new Client)->gatewayTypes(); - - $fees_and_limits = new \stdClass; - $fees_and_limits->{$gateway_types[0]} = new FeesAndLimits; - - $company_gateway->fees_and_limits = $fees_and_limits; - $company_gateway->save(); + /*Always ensure at least one fees and limits object is set per gateway*/ + $gateway_types = $company_gateway->driver(new Client)->getAvailableMethods(); + + $fees_and_limits = $company_gateway->fees_and_limits; + + foreach($gateway_types as $key => $gateway_type) + { + if(!property_exists($fees_and_limits, $key)) + $fees_and_limits->{$key} = new FeesAndLimits; } + $company_gateway->fees_and_limits = $fees_and_limits; + $company_gateway->save(); + ApplePayDomain::dispatch($company_gateway, $company_gateway->company->db); if (in_array($company_gateway->gateway_key, $this->stripe_keys)) { @@ -382,10 +388,18 @@ class CompanyGatewayController extends BaseController { $company_gateway->fill($request->all()); - if (! $request->has('fees_and_limits')) { - $company_gateway->fees_and_limits = ''; + /*Always ensure at least one fees and limits object is set per gateway*/ + $gateway_types = $company_gateway->driver(new Client)->getAvailableMethods(); + + $fees_and_limits = $company_gateway->fees_and_limits; + + foreach($gateway_types as $key => $gateway_type) { + if(!property_exists($fees_and_limits, $key)) { + $fees_and_limits->{$key} = new FeesAndLimits; + } } + $company_gateway->fees_and_limits = $fees_and_limits; $company_gateway->save(); if($company_gateway->gateway_key == $this->checkout_key) { diff --git a/app/Http/Requests/CompanyGateway/StoreCompanyGatewayRequest.php b/app/Http/Requests/CompanyGateway/StoreCompanyGatewayRequest.php index 5f148f5043..d007de2427 100644 --- a/app/Http/Requests/CompanyGateway/StoreCompanyGatewayRequest.php +++ b/app/Http/Requests/CompanyGateway/StoreCompanyGatewayRequest.php @@ -11,6 +11,7 @@ namespace App\Http\Requests\CompanyGateway; +use App\DataMapper\FeesAndLimits; use App\Http\Requests\Request; use App\Http\ValidationRules\ValidCompanyGatewayFeesAndLimitsRule; use App\Models\Gateway; @@ -28,7 +29,10 @@ class StoreCompanyGatewayRequest extends Request */ public function authorize() : bool { - return auth()->user()->isAdmin(); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->isAdmin(); } public function rules() @@ -64,6 +68,7 @@ class StoreCompanyGatewayRequest extends Request if (isset($input['fees_and_limits'])) { $input['fees_and_limits'] = $this->cleanFeesAndLimits($input['fees_and_limits']); } + } $this->replace($input); diff --git a/app/Http/Requests/CompanyGateway/UpdateCompanyGatewayRequest.php b/app/Http/Requests/CompanyGateway/UpdateCompanyGatewayRequest.php index 465449cce2..3949bdb804 100644 --- a/app/Http/Requests/CompanyGateway/UpdateCompanyGatewayRequest.php +++ b/app/Http/Requests/CompanyGateway/UpdateCompanyGatewayRequest.php @@ -27,7 +27,10 @@ class UpdateCompanyGatewayRequest extends Request */ public function authorize() { - return auth()->user()->isAdmin(); + /** @var \App\Models\User $user */ + $user = auth()->user(); + + return $user->isAdmin(); } public function rules() diff --git a/app/Models/CompanyGateway.php b/app/Models/CompanyGateway.php index 8525a88eb8..66c86f3b1a 100644 --- a/app/Models/CompanyGateway.php +++ b/app/Models/CompanyGateway.php @@ -117,7 +117,6 @@ class CompanyGateway extends BaseModel 16 => ['card' => 'images/credit_cards/Test-Discover-Icon.png', 'text' => 'Discover'], ]; - // const TYPE_PAYPAL = 300; // const TYPE_STRIPE = 301; // const TYPE_LEDGER = 302; @@ -132,6 +131,7 @@ class CompanyGateway extends BaseModel // const TYPE_MOLLIE = 312; // const TYPE_EWAY = 313; // const TYPE_FORTE = 314; + // const PAYPAL_PPCP = 323; public $gateway_consts = [ '38f2c48af60c7dd69e04248cbb24c36e' => 300, @@ -150,6 +150,7 @@ class CompanyGateway extends BaseModel '65faab2ab6e3223dbe848b1686490baz' => 320, 'b9886f9257f0c6ee7c302f1c74475f6c' => 321, 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9' => 322, + '80af24a6a691230bbec33e930ab40666' => 323, ]; protected $touches = []; diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 681889a68e..d811ea7ed0 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -90,7 +90,7 @@ class Gateway extends StaticModel if ($this->id == 1) { $link = 'http://reseller.authorize.net/application/?id=5560364'; - } elseif ($this->id == 15) { + } elseif (in_array($this->id,[15,60,61])) { $link = 'https://www.paypal.com/us/cgi-bin/webscr?cmd=_login-api-run'; } elseif ($this->id == 24) { $link = 'https://www.2checkout.com/referral?r=2c37ac2298'; @@ -202,7 +202,19 @@ class Gateway extends StaticModel // GatewayType::PRZELEWY24 => ['refund' => false, 'token_billing' => false], // GatewayType::SOFORT => ['refund' => false, 'token_billing' => false], ]; //Paypal - + case 61: + return [ + GatewayType::PAYPAL => ['refund' => false, 'token_billing' => false], + GatewayType::CREDIT_CARD => ['refund' => false, 'token_billing' => false], + GatewayType::VENMO => ['refund' => false, 'token_billing' => false], + // GatewayType::SEPA => ['refund' => false, 'token_billing' => false], + // GatewayType::BANCONTACT => ['refund' => false, 'token_billing' => false], + // GatewayType::EPS => ['refund' => false, 'token_billing' => false], + // GatewayType::MYBANK => ['refund' => false, 'token_billing' => false], + // GatewayType::PAYLATER => ['refund' => false, 'token_billing' => false], + // GatewayType::PRZELEWY24 => ['refund' => false, 'token_billing' => false], + // GatewayType::SOFORT => ['refund' => false, 'token_billing' => false], + ]; //Paypal PPCP default: return []; } diff --git a/app/Models/SystemLog.php b/app/Models/SystemLog.php index 781e2b1a7a..082f5280c2 100644 --- a/app/Models/SystemLog.php +++ b/app/Models/SystemLog.php @@ -148,6 +148,8 @@ class SystemLog extends Model const TYPE_RAZORPAY = 322; + const TYPE_PAYPAL_PPCP = 323; + const TYPE_QUOTA_EXCEEDED = 400; const TYPE_UPSTREAM_FAILURE = 401; diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index 7919cbe238..33309ae74f 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -109,6 +109,11 @@ class BaseDriver extends AbstractPaymentDriver return $this; } + public function getAvailableMethods(): array + { + return self::$methods; + } + /** * Required fields for client to fill, to proceed with gateway actions. * diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php new file mode 100644 index 0000000000..9df18d6522 --- /dev/null +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -0,0 +1,342 @@ + 'paypal', + 1 => 'card', + 25 => 'venmo', + // 9 => 'sepa', + // 12 => 'bancontact', + // 17 => 'eps', + // 15 => 'giropay', + // 13 => 'ideal', + // 26 => 'mercadopago', + // 27 => 'mybank', + // 28 => 'paylater', + // 16 => 'p24', + // 7 => 'sofort' + ]; + + public function gatewayTypes(): array + { + + $funding_options = []; + + foreach ($this->company_gateway->fees_and_limits as $key => $value) { + if ($value->is_enabled) { + $funding_options[] = $key; + } + } + + return $funding_options; + + } + + /** + * Initialize the Paypal gateway. + * + * Attempt to generate and return the access token. + * + * @return self + */ + public function init(): self + { + + $this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com'; + + $secret = $this->company_gateway->getConfigField('secret'); + + $client_id = $this->company_gateway->getConfigField('clientId'); + + if($this->access_token && $this->token_expiry && $this->token_expiry->isFuture()) + return $this; + + $response = Http::withBasicAuth($client_id, $secret) + ->withHeaders(['Content-Type' => 'application/x-www-form-urlencoded']) + ->withQueryParameters(['grant_type' => 'client_credentials']) + ->post("{$this->api_endpoint_url}/v1/oauth2/token"); + + if($response->successful()) { + $this->access_token = $response->json()['access_token']; + $this->token_expiry = now()->addSeconds($response->json()['expires_in'] - 60); + } else { + throw new PaymentFailed('Unable to gain access token from Paypal. Check your configuration', 401); + } + + return $this; + + } + + public function setPaymentMethod($payment_method_id) + { + if(!$payment_method_id) { + return $this; + } + + $this->paypal_payment_method = $this->funding_options[$payment_method_id]; + + return $this; + } + + public function authorizeView($payment_method) + { + // PayPal doesn't support direct authorization. + + return $this; + } + + public function authorizeResponse($request) + { + // PayPal doesn't support direct authorization. + + return $this; + } + + public function processPaymentView($data) + { + $this->init(); + + $data['gateway'] = $this; + + $this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]); + $this->payment_hash->save(); + + $data['client_id'] = $this->company_gateway->getConfigField('clientId'); + $data['token'] = $this->access_token; + $data['order_id'] = $this->createOrder($data); + $data['funding_options'] = $this->paypal_payment_method; + + return render('gateways.paypal.pay', $data); + + } + + private function getFundingOptions():string + { + + $enums = [ + 3 => 'paypal', + 1 => 'card', + 25 => 'venmo', + // 9 => 'sepa', + // 12 => 'bancontact', + // 17 => 'eps', + // 15 => 'giropay', + // 13 => 'ideal', + // 26 => 'mercadopago', + // 27 => 'mybank', + // 28 => 'paylater', + // 16 => 'p24', + // 7 => 'sofort' + ]; + + $funding_options = ''; + + foreach($this->company_gateway->fees_and_limits as $key => $value) { + + if($value->is_enabled) { + + $funding_options .=$enums[$key].','; + + } + + } + + return rtrim($funding_options, ','); + + } + + public function processPaymentResponse($request) + { + + // $response = json_decode($request['gateway_response'], true); + + // if($response['status'] == 'COMPLETED' && isset($response['purchase_units'])) { + + // $data = [ + // 'payment_type' => PaymentType::PAYPAL, + // 'amount' => $response['purchase_units'][0]['amount']['value'], + // 'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'], + // 'gateway_type_id' => GatewayType::PAYPAL, + // ]; + + // $payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); + + // SystemLogger::dispatch( + // ['response' => $response, 'data' => $data], + // SystemLog::CATEGORY_GATEWAY_RESPONSE, + // SystemLog::EVENT_GATEWAY_SUCCESS, + // SystemLog::TYPE_PAYPAL, + // $this->client, + // $this->client->company, + // ); + + // return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + + // } else { + + // SystemLogger::dispatch( + // ['response' => $response], + // SystemLog::CATEGORY_GATEWAY_RESPONSE, + // SystemLog::EVENT_GATEWAY_FAILURE, + // SystemLog::TYPE_PAYPAL, + // $this->client, + // $this->client->company, + // ); + + + // throw new PaymentFailed('Payment failed. Please try again.', 401); + // } + } + + private function createOrder(array $data): string + { + + $_invoice = collect($this->payment_hash->data->invoices)->first(); + + $invoice = Invoice::withTrashed()->find($this->decodePrimaryKey($_invoice->invoice_id)); + + $order = [ + "intent" => "CAPTURE", + "payer" => [ + "name" => [ + "given_name" => $this->client->present()->first_name(), + "surname" => $this->client->present()->last_name(), + ], + "email_address" => $this->client->present()->email(), + "address" => [ + "address_line_1" => $this->client->address1, + "address_line_2" => $this->client->address2, + "admin_area_1" => $this->client->city, + "admin_area_2" => $this->client->state, + "postal_code" => $this->client->postal_code, + "country_code" => $this->client->country->iso_3166_2, + ] + ], + "purchase_units" => [ + [ + "description" =>ctrans('texts.invoice_number').'# '.$invoice->number, + "invoice_id" => $invoice->number, + "amount" => [ + "value" => (string)$data['amount_with_fee'], + "currency_code"=> $this->client->currency()->code, + "breakdown" => [ + "item_total" => [ + "currency_code" => $this->client->currency()->code, + "value" => (string)$data['amount_with_fee'] + ] + ] + ], + "items"=> [ + [ + "name" => ctrans('texts.invoice_number').'# '.$invoice->number, + "quantity" => "1", + "unit_amount" => [ + "currency_code" => $this->client->currency()->code, + "value" => (string)$data['amount_with_fee'] + ], + ], + ], + ] + ] + ]; + + $r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order); + + return $r->json()['id']; + + } + + public function gatewayRequest(string $uri, string $verb, array $data, ?array $headers = []) + { + $this->init(); + + $r = Http::withToken($this->access_token) + ->withHeaders($this->getHeaders($headers)) + ->{$verb}("{$this->api_endpoint_url}{$uri}", $data); + + if($r->successful()) { + return $r; + } + + throw new PaymentFailed("Gateway failure - {$r->body()}", 401); + + } + + private function getHeaders(array $headers = []): array + { + return array_merge([ + 'Accept' => 'application/json', + 'Content-type' => 'application/json', + 'Accept-Language' => 'en_US', + 'PayPal-Partner-Attribution-Id' => 'invoiceninja_SP_PPCP' + ], $headers); + } + + private function feeCalc($invoice, $invoice_total) + { + // $invoice->service()->removeUnpaidGatewayFees(); + // $invoice = $invoice->fresh(); + + // $balance = floatval($invoice->balance); + + // $_updated_invoice = $invoice->service()->addGatewayFee($this->company_gateway, GatewayType::PAYPAL, $invoice_total)->save(); + + // if (floatval($_updated_invoice->balance) > $balance) { + // $fee = floatval($_updated_invoice->balance) - $balance; + + // $this->payment_hash->fee_total = $fee; + // $this->payment_hash->save(); + + // return $fee; + // } + + // return 0; + // } + + + } +} \ No newline at end of file diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index a80c09789d..61387efac9 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -139,13 +139,13 @@ class StripePaymentDriver extends BaseDriver return $this; } + /** * Returns the gateway types. */ public function gatewayTypes(): array { $types = [ - // GatewayType::CRYPTO, GatewayType::CREDIT_CARD, ]; diff --git a/config/ninja.php b/config/ninja.php index 7ef548ab7e..47fbe012a6 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -84,6 +84,7 @@ return [ 'password' => 'password', 'stripe' => env('STRIPE_KEYS', ''), 'paypal' => env('PAYPAL_KEYS', ''), + 'ppcp' => env('PPCP_KEYS', ''), 'paypal_rest' => env('PAYPAL_REST_KEYS', ''), 'authorize' => env('AUTHORIZE_KEYS', ''), 'checkout' => env('CHECKOUT_KEYS', ''), @@ -221,4 +222,8 @@ return [ 'client_id' => env('SHOPIFY_CLIENT_ID', null), 'client_secret' => env('SHOPIFY_CLIENT_SECRET', null), ], + 'paypal' => [ + 'secret' => env('PAYPAL_SECRET', null), + 'client_id' => env('PAYPAL_CLIENT_ID', null), + ] ]; diff --git a/database/migrations/2023_10_15_204204_add_paypal_ppcp.php b/database/migrations/2023_10_15_204204_add_paypal_ppcp.php new file mode 100644 index 0000000000..9adb8b1806 --- /dev/null +++ b/database/migrations/2023_10_15_204204_add_paypal_ppcp.php @@ -0,0 +1,49 @@ +clientId = ""; + $fields->secret = ""; + $fields->testMode = false; + + $paypal = new Gateway; + $paypal->id = 61; + $paypal->name = 'PayPal Platform'; + $paypal->key = '80af24a6a691230bbec33e930ab40666'; + $paypal->provider = 'PayPal_PPCP'; + $paypal->is_offsite = false; + $paypal->fields = \json_encode($fields); + $paypal->visible = 1; + $paypal->site_url = 'https://www.paypal.com/'; + $paypal->save(); + + } + + Gateway::whereIn('id', [60, 15])->update(['visible' => 0]); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/database/seeders/PaymentLibrariesSeeder.php b/database/seeders/PaymentLibrariesSeeder.php index 6803c4bf5f..ade9e6f7d9 100644 --- a/database/seeders/PaymentLibrariesSeeder.php +++ b/database/seeders/PaymentLibrariesSeeder.php @@ -84,6 +84,7 @@ class PaymentLibrariesSeeder extends Seeder ['id' => 58, 'name' => 'Razorpay', 'provider' => 'Razorpay', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9', 'fields' => '{"apiKey":"","apiSecret":""}'], ['id' => 59, 'name' => 'Forte', 'provider' => 'Forte', 'is_offsite' => false, 'sort_order' => 21, 'key' => 'kivcvjexxvdiyqtj3mju5d6yhpeht2xs', 'fields' => '{"testMode":false,"apiLoginId":"","apiAccessId":"","secureKey":"","authOrganizationId":"","organizationId":"","locationId":""}'], ['id' => 60, 'name' => 'PayPal REST', 'provider' => 'PayPal_Rest', 'key' => '80af24a6a691230bbec33e930ab40665', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'], + ['id' => 61, 'name' => 'PayPal Platform', 'provider' => 'PayPal_PPCP', 'key' => '80af24a6a691230bbec33e930ab40666', 'fields' => '{"clientId":"","secret":"","signature":"","testMode":false}'], ]; foreach ($gateways as $gateway) { @@ -100,12 +101,11 @@ class PaymentLibrariesSeeder extends Seeder Gateway::query()->update(['visible' => 0]); - Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59,60])->update(['visible' => 1]); + Gateway::whereIn('id', [1,3,7,11,15,20,39,46,55,50,57,52,58,59,60,61])->update(['visible' => 1]); if (Ninja::isHosted()) { - Gateway::whereIn('id', [20])->update(['visible' => 0]); - Gateway::whereIn('id', [56])->update(['visible' => 1]); - Gateway::whereIn('id', [49])->update(['visible' => 1]); + Gateway::whereIn('id', [20,49])->update(['visible' => 0]); + Gateway::whereIn('id', [56,61])->update(['visible' => 1]); } Gateway::all()->each(function ($gateway) { diff --git a/public/build/assets/eway-credit-card-62ce5f3b.js b/public/build/assets/eway-credit-card-62ce5f3b.js new file mode 100644 index 0000000000..3c3ceed101 --- /dev/null +++ b/public/build/assets/eway-credit-card-62ce5f3b.js @@ -0,0 +1,9 @@ +/** + * 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 i{constructor(){this.cardStyles="padding: 2px; border: 1px solid #AAA; border-radius: 3px; height: 34px; width: 100%;",this.errorCodes=new Map,this.errorCodes.set("V6000","Validation error"),this.errorCodes.set("V6001","Invalid CustomerIP"),this.errorCodes.set("V6002","Invalid DeviceID"),this.errorCodes.set("V6003","Invalid Request PartnerID"),this.errorCodes.set("V6004","Invalid Request Method"),this.errorCodes.set("V6010","Invalid TransactionType, account not certified for eCome only MOTO or Recurring available"),this.errorCodes.set("V6011","Invalid Payment TotalAmount"),this.errorCodes.set("V6012","Invalid Payment InvoiceDescription"),this.errorCodes.set("V6013","Invalid Payment InvoiceNumber"),this.errorCodes.set("V6014","Invalid Payment InvoiceReference"),this.errorCodes.set("V6015","Invalid Payment CurrencyCode"),this.errorCodes.set("V6016","Payment Required"),this.errorCodes.set("V6017","Payment CurrencyCode Required"),this.errorCodes.set("V6018","Unknown Payment CurrencyCode"),this.errorCodes.set("V6019","Cardholder identity authentication required"),this.errorCodes.set("V6020","Cardholder Input Required"),this.errorCodes.set("V6021","EWAY_CARDHOLDERNAME Required"),this.errorCodes.set("V6022","EWAY_CARDNUMBER Required"),this.errorCodes.set("V6023","EWAY_CARDCVN Required"),this.errorCodes.set("V6024","Cardholder Identity Authentication One Time Password Not Active Yet"),this.errorCodes.set("V6025","PIN Required"),this.errorCodes.set("V6033","Invalid Expiry Date"),this.errorCodes.set("V6034","Invalid Issue Number"),this.errorCodes.set("V6035","Invalid Valid From Date"),this.errorCodes.set("V6039","Invalid Network Token Status"),this.errorCodes.set("V6040","Invalid TokenCustomerID"),this.errorCodes.set("V6041","Customer Required"),this.errorCodes.set("V6042","Customer FirstName Required"),this.errorCodes.set("V6043","Customer LastName Required"),this.errorCodes.set("V6044","Customer CountryCode Required"),this.errorCodes.set("V6045","Customer Title Required"),this.errorCodes.set("V6046","TokenCustomerID Required"),this.errorCodes.set("V6047","RedirectURL Required"),this.errorCodes.set("V6048","CheckoutURL Required when CheckoutPayment specified"),this.errorCodes.set("V6049","nvalid Checkout URL"),this.errorCodes.set("V6051","Invalid Customer FirstName"),this.errorCodes.set("V6052","Invalid Customer LastName"),this.errorCodes.set("V6053","Invalid Customer CountryCode"),this.errorCodes.set("V6058","Invalid Customer Title"),this.errorCodes.set("V6059","Invalid RedirectURL"),this.errorCodes.set("V6060","Invalid TokenCustomerID"),this.errorCodes.set("V6061","Invalid Customer Reference"),this.errorCodes.set("V6062","Invalid Customer CompanyName"),this.errorCodes.set("V6063","Invalid Customer JobDescription"),this.errorCodes.set("V6064","Invalid Customer Street1"),this.errorCodes.set("V6065","Invalid Customer Street2"),this.errorCodes.set("V6066","Invalid Customer City"),this.errorCodes.set("V6067","Invalid Customer State"),this.errorCodes.set("V6068","Invalid Customer PostalCode"),this.errorCodes.set("V6069","Invalid Customer Email"),this.errorCodes.set("V6070","Invalid Customer Phone"),this.errorCodes.set("V6071","Invalid Customer Mobile"),this.errorCodes.set("V6072","Invalid Customer Comments"),this.errorCodes.set("V6073","Invalid Customer Fax"),this.errorCodes.set("V6074","Invalid Customer URL"),this.errorCodes.set("V6075","Invalid ShippingAddress FirstName"),this.errorCodes.set("V6076","Invalid ShippingAddress LastName"),this.errorCodes.set("V6077","Invalid ShippingAddress Street1"),this.errorCodes.set("V6078","Invalid ShippingAddress Street2"),this.errorCodes.set("V6079","Invalid ShippingAddress City"),this.errorCodes.set("V6080","Invalid ShippingAddress State"),this.errorCodes.set("V6081","Invalid ShippingAddress PostalCode"),this.errorCodes.set("V6082","Invalid ShippingAddress Email"),this.errorCodes.set("V6083","Invalid ShippingAddress Phone"),this.errorCodes.set("V6084","Invalid ShippingAddress Country"),this.errorCodes.set("V6085","Invalid ShippingAddress ShippingMethod"),this.errorCodes.set("V6086","Invalid ShippingAddress Fax"),this.errorCodes.set("V6091","Unknown Customer CountryCode"),this.errorCodes.set("V6092","Unknown ShippingAddress CountryCode"),this.errorCodes.set("V6093","Insufficient Address Information"),this.errorCodes.set("V6100","Invalid EWAY_CARDNAME"),this.errorCodes.set("V6101","Invalid EWAY_CARDEXPIRYMONTH"),this.errorCodes.set("V6102","Invalid EWAY_CARDEXPIRYYEAR"),this.errorCodes.set("V6103","Invalid EWAY_CARDSTARTMONTH"),this.errorCodes.set("V6104","Invalid EWAY_CARDSTARTYEAR"),this.errorCodes.set("V6105","Invalid EWAY_CARDISSUENUMBER"),this.errorCodes.set("V6106","Invalid EWAY_CARDCVN"),this.errorCodes.set("V6107","Invalid EWAY_ACCESSCODE"),this.errorCodes.set("V6108","Invalid CustomerHostAddress"),this.errorCodes.set("V6109","Invalid UserAgent"),this.errorCodes.set("V6110","Invalid EWAY_CARDNUMBER"),this.errorCodes.set("V6111","Unauthorised API Access, Account Not PCI Certified"),this.errorCodes.set("V6112","Redundant card details other than expiry year and month"),this.errorCodes.set("V6113","Invalid transaction for refund"),this.errorCodes.set("V6114","Gateway validation error"),this.errorCodes.set("V6115","Invalid DirectRefundRequest, Transaction ID"),this.errorCodes.set("V6116","Invalid card data on original TransactionID"),this.errorCodes.set("V6117","Invalid CreateAccessCodeSharedRequest, FooterText"),this.errorCodes.set("V6118","Invalid CreateAccessCodeSharedRequest, HeaderText"),this.errorCodes.set("V6119","Invalid CreateAccessCodeSharedRequest, Language"),this.errorCodes.set("V6120","Invalid CreateAccessCodeSharedRequest, LogoUrl"),this.errorCodes.set("V6121","Invalid TransactionSearch, Filter Match Type"),this.errorCodes.set("V6122","Invalid TransactionSearch, Non numeric Transaction ID"),this.errorCodes.set("V6123","Invalid TransactionSearch,no TransactionID or AccessCode specified"),this.errorCodes.set("V6124","Invalid Line Items. The line items have been provided however the totals do not match the TotalAmount field"),this.errorCodes.set("V6125","Selected Payment Type not enabled"),this.errorCodes.set("V6126","Invalid encrypted card number, decryption failed"),this.errorCodes.set("V6127","Invalid encrypted cvn, decryption failed"),this.errorCodes.set("V6128","Invalid Method for Payment Type"),this.errorCodes.set("V6129","Transaction has not been authorised for Capture/Cancellation"),this.errorCodes.set("V6130","Generic customer information error"),this.errorCodes.set("V6131","Generic shipping information error"),this.errorCodes.set("V6132","Transaction has already been completed or voided, operation not permitted"),this.errorCodes.set("V6133","Checkout not available for Payment Type"),this.errorCodes.set("V6134","Invalid Auth Transaction ID for Capture/Void"),this.errorCodes.set("V6135","PayPal Error Processing Refund"),this.errorCodes.set("V6136","Original transaction does not exist or state is incorrect"),this.errorCodes.set("V6140","Merchant account is suspended"),this.errorCodes.set("V6141","Invalid PayPal account details or API signature"),this.errorCodes.set("V6142","Authorise not available for Bank/Branch"),this.errorCodes.set("V6143","Invalid Public Key"),this.errorCodes.set("V6144","Method not available with Public API Key Authentication"),this.errorCodes.set("V6145","Credit Card not allow if Token Customer ID is provided with Public API Key Authentication"),this.errorCodes.set("V6146","Client Side Encryption Key Missing or Invalid"),this.errorCodes.set("V6147","Unable to Create One Time Code for Secure Field"),this.errorCodes.set("V6148","Secure Field has Expired"),this.errorCodes.set("V6149","Invalid Secure Field One Time Code"),this.errorCodes.set("V6150","Invalid Refund Amount"),this.errorCodes.set("V6151","Refund amount greater than original transaction"),this.errorCodes.set("V6152","Original transaction already refunded for total amount"),this.errorCodes.set("V6153","Card type not support by merchant"),this.errorCodes.set("V6154","Insufficent Funds Available For Refund"),this.errorCodes.set("V6155","Missing one or more fields in request"),this.errorCodes.set("V6160","Encryption Method Not Supported"),this.errorCodes.set("V6161","Encryption failed, missing or invalid key"),this.errorCodes.set("V6165","Invalid Click-to-Pay (Visa Checkout) data or decryption failed"),this.errorCodes.set("V6170","Invalid TransactionSearch, Invoice Number is not unique"),this.errorCodes.set("V6171","Invalid TransactionSearch, Invoice Number not found"),this.errorCodes.set("V6220","Three domain secure XID invalid"),this.errorCodes.set("V6221","Three domain secure ECI invalid"),this.errorCodes.set("V6222","Three domain secure AVV invalid"),this.errorCodes.set("V6223","Three domain secure XID is required"),this.errorCodes.set("V6224","Three Domain Secure ECI is required"),this.errorCodes.set("V6225","Three Domain Secure AVV is required"),this.errorCodes.set("V6226","Three Domain Secure AuthStatus is required"),this.errorCodes.set("V6227","Three Domain Secure AuthStatus invalid"),this.errorCodes.set("V6228","Three domain secure Version is required"),this.errorCodes.set("V6230","Three domain secure Directory Server Txn ID invalid"),this.errorCodes.set("V6231","Three domain secure Directory Server Txn ID is required"),this.errorCodes.set("V6232","Three domain secure Version is invalid"),this.errorCodes.set("V6501","Invalid Amex InstallementPlan"),this.errorCodes.set("V6502","Invalid Number Of Installements for Amex. Valid values are from 0 to 99 inclusive"),this.errorCodes.set("V6503","Merchant Amex ID required"),this.errorCodes.set("V6504","Invalid Merchant Amex ID"),this.errorCodes.set("V6505","Merchant Terminal ID required"),this.errorCodes.set("V6506","Merchant category code required"),this.errorCodes.set("V6507","Invalid merchant category code"),this.errorCodes.set("V6508","Amex 3D ECI required"),this.errorCodes.set("V6509","Invalid Amex 3D ECI"),this.errorCodes.set("V6510","Invalid Amex 3D verification value"),this.errorCodes.set("V6511","Invalid merchant location data"),this.errorCodes.set("V6512","Invalid merchant street address"),this.errorCodes.set("V6513","Invalid merchant city"),this.errorCodes.set("V6514","Invalid merchant country"),this.errorCodes.set("V6515","Invalid merchant phone"),this.errorCodes.set("V6516","Invalid merchant postcode"),this.errorCodes.set("V6517","Amex connection error"),this.errorCodes.set("V6518","Amex EC Card Details API returned invalid data"),this.errorCodes.set("V6520","Invalid or missing Amex Point Of Sale Data"),this.errorCodes.set("V6521","Invalid or missing Amex transaction date time"),this.errorCodes.set("V6522","Invalid or missing Amex Original transaction date time"),this.errorCodes.set("V6530","Credit Card Number in non Credit Card Field")}get groupFieldConfig(){var e,t,r,s,o;return{publicApiKey:(e=document.querySelector("meta[name=public-api-key]"))==null?void 0:e.content,fieldDivId:"eway-secure-panel",fieldType:"group",styles:"",layout:{fonts:["Lobster"],rows:[{styles:"",cells:[{colSpan:12,styles:"margin-top: 15px;",label:{fieldColSpan:4,text:(t=document.querySelector("meta[name=translation-card-name]"))==null?void 0:t.content,styles:""},field:{fieldColSpan:8,fieldType:"name",styles:this.cardStyles,divStyles:"padding-left: 10px;"}},{colSpan:12,styles:"margin-top: 15px;",label:{fieldColSpan:4,text:(r=document.querySelector("meta[name=translation-expiry_date]"))==null?void 0:r.content,styles:""},field:{fieldColSpan:8,fieldType:"expirytext",styles:this.cardStyles,divStyles:"padding-left: 10px;"}}]},{styles:"",cells:[{colSpan:12,styles:"margin-top: 15px;",label:{fieldColSpan:4,text:(s=document.querySelector("meta[name=translation-card_number]"))==null?void 0:s.content,styles:""},field:{fieldColSpan:8,fieldType:"card",styles:this.cardStyles}},{colSpan:12,styles:"margin-top: 15px;",label:{fieldColSpan:4,text:(o=document.querySelector("meta[name=translation-cvv]"))==null?void 0:o.content,styles:""},field:{fieldColSpan:8,fieldType:"cvn",styles:this.cardStyles}}]}]}}}securePanelCallback(e){if(document.getElementById("errors").hidden=!0,e.errors)return this.handleErrors(e.errors);document.getElementById("authorize-card")&&(document.getElementById("authorize-card").disabled=!1),document.getElementById("pay-now")&&(document.getElementById("pay-now").disabled=!1),document.querySelector("input[name=securefieldcode]").value=e.secureFieldCode}handleErrors(e){let t=e.split(" "),r="";t.forEach(s=>{r=r.concat(this.errorCodes.get(s)+"
")}),document.getElementById("errors").innerHTML=r,document.getElementById("errors").hidden=!1}completeAuthorization(e){e.target.parentElement.disabled=!0,document.getElementById("server-response").submit()}completePaymentUsingToken(e){e.target.parentElement.disabled=!0,document.getElementById("server-response").submit()}completePaymentWithoutToken(e){e.target.parentElement.disabled=!0;let t=document.querySelector('input[name="token-billing-checkbox"]:checked');t&&(document.querySelector('input[name="store_card"]').value=t.value),document.getElementById("server-response").submit()}initialize(){this.eWAY=eWAY.setupSecureField(this.groupFieldConfig,e=>this.securePanelCallback(e))}handle(){var e,t;this.initialize(),(e=document.getElementById("authorize-card"))==null||e.addEventListener("click",r=>this.completeAuthorization(r)),Array.from(document.getElementsByClassName("toggle-payment-with-token")??[]).forEach(r=>r.addEventListener("click",s=>{document.getElementById("eway-secure-panel").classList.add("hidden"),document.getElementById("save-card--container").style.display="none",document.querySelector("input[name=token]").value=s.target.dataset.token,document.getElementById("pay-now").disabled=!1})),document.getElementById("toggle-payment-with-credit-card")&&document.getElementById("toggle-payment-with-credit-card").addEventListener("click",r=>{document.getElementById("eway-secure-panel").classList.remove("hidden"),document.getElementById("save-card--container").style.display="grid",document.querySelector("input[name=token]").value="",document.getElementById("pay-now").disabled=!0}),(t=document.getElementById("pay-now"))==null||t.addEventListener("click",r=>document.querySelector("input[name=token]").value?this.completePaymentUsingToken(r):this.completePaymentWithoutToken(r))}}new i().handle(); From 55059d1227b2c498cf60cb0744fabf8ef5921fd9 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 15:48:45 +1100 Subject: [PATCH 02/42] Paypal CC --- .../PayPalPPCPPaymentDriver.php | 27 +++++-- .../gateways/paypal/credit_card/pay.blade.php | 71 +++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 resources/views/portal/ninja2020/gateways/paypal/credit_card/pay.blade.php diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php index 9df18d6522..52e6d510a1 100644 --- a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -41,7 +41,7 @@ class PayPalPPCPPaymentDriver extends BaseDriver private string $paypal_payment_method = ''; - protected ?string $access_token = null; + protected mixed $access_token = null; protected ?Carbon $token_expiry = null; @@ -61,6 +61,12 @@ class PayPalPPCPPaymentDriver extends BaseDriver // 7 => 'sofort' ]; + /** + * Return an array of + * enabled gateway payment methods + * + * @return array + */ public function gatewayTypes(): array { @@ -141,16 +147,27 @@ class PayPalPPCPPaymentDriver extends BaseDriver $this->init(); $data['gateway'] = $this; - $this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]); $this->payment_hash->save(); $data['client_id'] = $this->company_gateway->getConfigField('clientId'); - $data['token'] = $this->access_token; + $data['token'] = $this->getClientToken(); $data['order_id'] = $this->createOrder($data); $data['funding_options'] = $this->paypal_payment_method; - return render('gateways.paypal.pay', $data); + return render('gateways.paypal.credit_card.pay', $data); + + } + + private function getClientToken(): string + { + + $r = $this->gatewayRequest('/v1/identity/generate-token', 'post', ['body' => '']); + + if($r->successful()) + return $r->json()['client_token']; + + throw new PaymentFailed('Unable to gain client token from Paypal. Check your configuration', 401); } @@ -286,6 +303,8 @@ class PayPalPPCPPaymentDriver extends BaseDriver $r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order); + nlog($r->json()); + return $r->json()['id']; } diff --git a/resources/views/portal/ninja2020/gateways/paypal/credit_card/pay.blade.php b/resources/views/portal/ninja2020/gateways/paypal/credit_card/pay.blade.php new file mode 100644 index 0000000000..e658cb073b --- /dev/null +++ b/resources/views/portal/ninja2020/gateways/paypal/credit_card/pay.blade.php @@ -0,0 +1,71 @@ +@extends('portal.ninja2020.layout.payments', ['gateway_title' => ctrans('texts.payment_type_credit_card'), 'card_title' => 'PayPal']) + +@section('gateway_head') + + +@endsection + +@section('gateway_content') +
+ @csrf + + + + +
+ + + +
+ +@endsection + +@section('gateway_footer') +@endsection + +@push('footer') + + + +
+ + +@endpush \ No newline at end of file From 6ca1a36ef47c69c3967ea369bd50abc07be40191 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 16:23:04 +1100 Subject: [PATCH 03/42] Fixes for ppcp --- .../PayPalPPCPPaymentDriver.php | 82 ++++++++++--------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php index 52e6d510a1..e51d82f7c2 100644 --- a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -70,15 +70,21 @@ class PayPalPPCPPaymentDriver extends BaseDriver public function gatewayTypes(): array { - $funding_options = []; - - foreach ($this->company_gateway->fees_and_limits as $key => $value) { - if ($value->is_enabled) { - $funding_options[] = $key; - } - } - - return $funding_options; + // $funding_options = []; + + // foreach ($this->company_gateway->fees_and_limits as $key => $value) { + // if ($value->is_enabled) { + // $funding_options[] = (int)$key; + // } + // } + return collect($this->company_gateway->fees_and_limits) + ->filter(function ($fee){ + return $fee->is_enabled; + })->map(function ($fee, $key){ + return (int)$key; + })->toArray(); + + // return $funding_options; } @@ -209,44 +215,44 @@ class PayPalPPCPPaymentDriver extends BaseDriver public function processPaymentResponse($request) { - // $response = json_decode($request['gateway_response'], true); + $response = json_decode($request['gateway_response'], true); - // if($response['status'] == 'COMPLETED' && isset($response['purchase_units'])) { + if($response['status'] == 'COMPLETED' && isset($response['purchase_units'])) { - // $data = [ - // 'payment_type' => PaymentType::PAYPAL, - // 'amount' => $response['purchase_units'][0]['amount']['value'], - // 'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'], - // 'gateway_type_id' => GatewayType::PAYPAL, - // ]; + $data = [ + 'payment_type' => PaymentType::PAYPAL, + 'amount' => $response['purchase_units'][0]['amount']['value'], + 'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'], + 'gateway_type_id' => GatewayType::PAYPAL, + ]; - // $payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); + $payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); - // SystemLogger::dispatch( - // ['response' => $response, 'data' => $data], - // SystemLog::CATEGORY_GATEWAY_RESPONSE, - // SystemLog::EVENT_GATEWAY_SUCCESS, - // SystemLog::TYPE_PAYPAL, - // $this->client, - // $this->client->company, - // ); + SystemLogger::dispatch( + ['response' => $response, 'data' => $data], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_SUCCESS, + SystemLog::TYPE_PAYPAL, + $this->client, + $this->client->company, + ); - // return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); + return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); - // } else { + } else { - // SystemLogger::dispatch( - // ['response' => $response], - // SystemLog::CATEGORY_GATEWAY_RESPONSE, - // SystemLog::EVENT_GATEWAY_FAILURE, - // SystemLog::TYPE_PAYPAL, - // $this->client, - // $this->client->company, - // ); + SystemLogger::dispatch( + ['response' => $response], + SystemLog::CATEGORY_GATEWAY_RESPONSE, + SystemLog::EVENT_GATEWAY_FAILURE, + SystemLog::TYPE_PAYPAL, + $this->client, + $this->client->company, + ); - // throw new PaymentFailed('Payment failed. Please try again.', 401); - // } + throw new PaymentFailed('Payment failed. Please try again.', 401); + } } private function createOrder(array $data): string From 15941b8273eae66b5fa4927dfcacf05fabf03e00 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 16:29:34 +1100 Subject: [PATCH 04/42] Renaming --- app/PaymentDrivers/PayPalPPCPPaymentDriver.php | 4 ++-- .../gateways/paypal/{credit_card => ppcp}/pay.blade.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename resources/views/portal/ninja2020/gateways/paypal/{credit_card => ppcp}/pay.blade.php (98%) diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php index e51d82f7c2..a4f17de6fa 100644 --- a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -159,9 +159,9 @@ class PayPalPPCPPaymentDriver extends BaseDriver $data['client_id'] = $this->company_gateway->getConfigField('clientId'); $data['token'] = $this->getClientToken(); $data['order_id'] = $this->createOrder($data); - $data['funding_options'] = $this->paypal_payment_method; + $data['funding_source'] = $this->paypal_payment_method; - return render('gateways.paypal.credit_card.pay', $data); + return render('gateways.paypal.ppcp.pay', $data); } diff --git a/resources/views/portal/ninja2020/gateways/paypal/credit_card/pay.blade.php b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php similarity index 98% rename from resources/views/portal/ninja2020/gateways/paypal/credit_card/pay.blade.php rename to resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php index e658cb073b..fbb5fb6913 100644 --- a/resources/views/portal/ninja2020/gateways/paypal/credit_card/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php @@ -36,7 +36,7 @@ paypal.Buttons({ env: "{{ $gateway->company_gateway->getConfigField('testMode') ? 'sandbox' : 'production' }}", - fundingSource: "card", + fundingSource: "{{ $funding_source }}", client: { @if($gateway->company_gateway->getConfigField('testMode')) sandbox: "{{ $gateway->company_gateway->getConfigField('clientId') }}" From 92e3f05e8b89abf5ffec697df329c37753e50129 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 16:49:47 +1100 Subject: [PATCH 05/42] Add translation for Venmo --- .../gateways/paypal/ppcp/pay.blade.php | 61 +++++++++---------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php index fbb5fb6913..9aa4b34ced 100644 --- a/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php @@ -29,43 +29,40 @@ @push('footer') - - -
- +
+ + @endpush \ No newline at end of file From 1f05c10cea0173b923b29c289bebe802c42a9490 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 16 Oct 2023 17:00:37 +1100 Subject: [PATCH 06/42] Working on payments --- app/PaymentDrivers/PayPalPPCPPaymentDriver.php | 2 ++ .../views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php index a4f17de6fa..d08eeda3e7 100644 --- a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -217,6 +217,8 @@ class PayPalPPCPPaymentDriver extends BaseDriver $response = json_decode($request['gateway_response'], true); + nlog($response); + if($response['status'] == 'COMPLETED' && isset($response['purchase_units'])) { $data = [ diff --git a/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php index 9aa4b34ced..2c2718b2d5 100644 --- a/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php @@ -32,6 +32,8 @@
+
+