From 95a8c2510f95099d5d85016c78cf7c819f078049 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 13 Dec 2023 20:01:34 +1100 Subject: [PATCH] Tests for rehydrating order for payment --- app/PaymentDrivers/PayPal/PayPalWebhook.php | 34 +++-- .../PayPalPPCPPaymentDriver.php | 10 +- .../gateways/paypal/ppcp/pay.blade.php | 7 +- tests/Feature/PayPal/WebhookTest.php | 144 ++++++++++++++++++ 4 files changed, 175 insertions(+), 20 deletions(-) create mode 100644 tests/Feature/PayPal/WebhookTest.php diff --git a/app/PaymentDrivers/PayPal/PayPalWebhook.php b/app/PaymentDrivers/PayPal/PayPalWebhook.php index d89d828d9f..d0911f1b1f 100644 --- a/app/PaymentDrivers/PayPal/PayPalWebhook.php +++ b/app/PaymentDrivers/PayPal/PayPalWebhook.php @@ -39,12 +39,22 @@ class PayPalWebhook implements ShouldQueue private $gateway_key = '80af24a6a691230bbec33e930ab40666'; + private string $test_endpoint = 'https://api-m.sandbox.paypal.com'; + + private string $endpoint = 'https://api-m.paypal.com'; + public function __construct(protected array $webhook_request, protected array $headers, protected string $access_token) { } public function handle() { + //testing + $this->endpoint = $this->test_endpoint; + + //this can cause problems verifying the webhook, so unset it if it exists + if(isset($this->webhook_request['q'])) + unset($this->webhook_request['q']); if($this->verifyWebhook()) { nlog('verified'); @@ -53,9 +63,10 @@ class PayPalWebhook implements ShouldQueue 'CHECKOUT.ORDER.COMPLETED' => $this->checkoutOrderCompleted(), }; - + return; } + nlog(" NOT VERIFIED "); } /* 'id' => 'WH-COC11055RA711503B-4YM959094A144403T', @@ -293,27 +304,26 @@ class PayPalWebhook implements ShouldQueue //--------------------------------------------------------------------------------------// private function verifyWebhook(): bool - { + {nlog($this->headers); $request = [ - 'auth_algo' => $this->headers['paypal-auth-algo'], - 'cert_url' => $this->headers['paypal-cert-url'], - 'transmission_id' => $this->headers['paypal-transmission-id'], - 'transmission_sig' => $this->headers['paypal-transmission-sig'], - 'transmission_time' => $this->headers['paypal-transmission-time'], + 'auth_algo' => $this->headers['paypal-auth-algo'][0], + 'cert_url' => $this->headers['paypal-cert-url'][0], + 'transmission_id' => $this->headers['paypal-transmission-id'][0], + 'transmission_sig' => $this->headers['paypal-transmission-sig'][0], + 'transmission_time' => $this->headers['paypal-transmission-time'][0], 'webhook_id' => config('ninja.paypal.webhook_id'), - 'webhook_event' => $this->webhook_request, + 'webhook_event' => $this->webhook_request ]; + nlog($request); + $headers = [ - 'Accept' => 'application/json', 'Content-type' => 'application/json', - 'Accept-Language' => 'en_US', - 'PayPal-Partner-Attribution-Id' => 'invoiceninja_SP_PPCP', ]; $r = Http::withToken($this->access_token) ->withHeaders($headers) - ->post("https://api-m.paypal.com/v1/notifications/verify-webhook-signature", $request); + ->post("{$this->endpoint}/v1/notifications/verify-webhook-signature", $request); nlog($r); nlog($r->json()); diff --git a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php index 72b74e27eb..f0b644f7c9 100644 --- a/app/PaymentDrivers/PayPalPPCPPaymentDriver.php +++ b/app/PaymentDrivers/PayPalPPCPPaymentDriver.php @@ -443,7 +443,7 @@ class PayPalPPCPPaymentDriver extends BaseDriver $r = $this->gatewayRequest('/v2/checkout/orders', 'post', $order); - nlog($r->json()); + // nlog($r->json()); return $r->json()['id']; @@ -499,8 +499,8 @@ class PayPalPPCPPaymentDriver extends BaseDriver ->withHeaders($this->getHeaders($headers)) ->{$verb}("{$this->api_endpoint_url}{$uri}", $data); - nlog($r); - nlog($r->json()); + // nlog($r); + // nlog($r->json()); if($r->successful()) { return $r; @@ -538,8 +538,8 @@ class PayPalPPCPPaymentDriver extends BaseDriver public function processWebhookRequest(Request $request) { - // nlog($request->all()); - // nlog($request->headers->all()); + + nlog(json_encode($request->all())); $this->init(); PayPalWebhook::dispatch($request->all(), $request->headers->all(), $this->access_token); 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 4570359a3e..c8fa4d438d 100644 --- a/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php +++ b/resources/views/portal/ninja2020/gateways/paypal/ppcp/pay.blade.php @@ -53,11 +53,9 @@ return actions.restart(); } - // return actions.order.capture().then(function(details) { document.getElementById("gateway_response").value =JSON.stringify( data ); - // document.getElementById("gateway_response").value =JSON.stringify( details ); document.getElementById("server_response").submit(); - // }); + }, onCancel: function() { window.location.href = "/client/invoices/"; @@ -65,6 +63,9 @@ onError: function(error) { document.getElementById("gateway_response").value = error; document.getElementById("server_response").submit(); + }, + onClick: function (){ + document.getElementById('paypal-button-container').hidden = true; } }).render('#paypal-button-container').catch(function(err) { diff --git a/tests/Feature/PayPal/WebhookTest.php b/tests/Feature/PayPal/WebhookTest.php new file mode 100644 index 0000000000..d98b4b88e9 --- /dev/null +++ b/tests/Feature/PayPal/WebhookTest.php @@ -0,0 +1,144 @@ +makeTestData(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + + } + + public function testWebhooks() + { + $hook = json_decode($this->webhook_string, true); + $this->assertIsArray($hook); + } + + public function testPaymentCreation() + { + $hook = json_decode($this->webhook_string, true); + + $company_gateway = $this->buildGateway(); + + $invoice = Invoice::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'number' => $this->invoice_number, + 'status_id' => 2, + 'amount' => $this->amount, + 'balance' => $this->amount, + ]); + + $hash_data = [ + 'invoices' => [ + ['invoice_id' => $invoice->hashed_id, 'amount' => $this->amount], + ], + 'credits' => 0, + 'amount_with_fee' => $this->amount, + 'pre_payment' => false, + 'frequency_id' => null, + 'remaining_cycles' => null, + 'is_recurring' => false, + ]; + + $payment_hash = new PaymentHash; + $payment_hash->hash = Str::random(32); + $payment_hash->data = $hash_data; + $payment_hash->fee_total = 0; + $payment_hash->fee_invoice_id = $invoice->id; + $payment_hash->save(); + + + $driver = $company_gateway->driver($this->client)->init(); + $driver->setPaymentHash($payment_hash); + + $source = 'paypal'; + $transaction_reference = $hook['resource']['purchase_units'][0]['payments']['captures'][0]['id']; + $amount = $hook['resource']['purchase_units'][0]['payments']['captures'][0]['amount']['value']; + + $data = [ + 'payment_type' => 3, + 'amount' => $amount, + 'transaction_reference' => $transaction_reference, + 'gateway_type_id' => GatewayType::PAYPAL, + ]; + + $payment = $driver->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); + + $this->assertNotNull($payment); + + + } + + private function buildGateway() + { + $config = new \stdClass; + $config->merchantId = $this->merchant_id; + $config->status = 'activated'; + $config->consent = 'true'; + $config->emailVerified = 'true'; + $config->permissions = 'true'; + $config->returnMessage = 'true'; + $config->paymentsReceivable = 'Yes'; + + $cg = new CompanyGateway; + $cg->company_id = $this->company->id; + $cg->user_id = $this->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); + $cg->save(); + + $fees_and_limits = new stdClass; + $fees_and_limits->{3} = new FeesAndLimits; + + $cg->fees_and_limits = $fees_and_limits; + $cg->save(); + + return $cg; + } +} \ No newline at end of file