From 3e151690f6d5e80f1d3ca6bb7957e2b0222f5768 Mon Sep 17 00:00:00 2001 From: Raza Mehdi Date: Wed, 13 Sep 2023 02:35:02 +0500 Subject: [PATCH] Refactor Invoices API implementation. --- src/Traits/PayPalAPI/Invoices.php | 250 +++++++++++---------- src/Traits/PayPalAPI/InvoicesTemplates.php | 48 ++-- tests/Feature/AdapterFeatureTest.php | 12 +- tests/Unit/Adapter/InvoicesTest.php | 12 +- 4 files changed, 177 insertions(+), 145 deletions(-) diff --git a/src/Traits/PayPalAPI/Invoices.php b/src/Traits/PayPalAPI/Invoices.php index 7c8bbcfc..4995bbd9 100644 --- a/src/Traits/PayPalAPI/Invoices.php +++ b/src/Traits/PayPalAPI/Invoices.php @@ -4,24 +4,6 @@ trait Invoices { - /** - * Generate the next invoice number. - * - * @throws \Throwable - * - * @return array|\Psr\Http\Message\StreamInterface|string - * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_generate-next-invoice-number - */ - public function generateInvoiceNumber() - { - $this->apiEndPoint = 'v2/invoicing/generate-next-invoice-number'; - - $this->verb = 'post'; - - return $this->doPayPalRequest(); - } - /** * Create a new draft invoice. * @@ -69,117 +51,86 @@ public function listInvoices(array $fields = []) } /** - * Delete an invoice. + * Send an existing invoice. * * @param string $invoice_id + * @param string $subject + * @param string $note + * @param bool $send_recipient + * @param bool $send_merchant + * @param array $recipients * * @throws \Throwable * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_list + * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_send */ - public function deleteInvoice(string $invoice_id) + public function sendInvoice(string $invoice_id, string $subject = '', string $note = '', bool $send_recipient = true, bool $send_merchant = false, array $recipients = []) { - $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}"; + $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/send"; - $this->verb = 'delete'; + $this->options['json'] = $this->getInvoiceMessagePayload($subject, $note, $recipients, $send_recipient, $send_merchant); + + $this->verb = 'post'; return $this->doPayPalRequest(false); } /** - * Update an existing invoice. + * Send reminder for an existing invoice. * * @param string $invoice_id - * @param array $data + * @param string $subject + * @param string $note + * @param bool $send_recipient + * @param bool $send_merchant + * @param array $recipients * * @throws \Throwable * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_update + * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_remind */ - public function updateInvoice(string $invoice_id, array $data) + public function sendInvoiceReminder(string $invoice_id, string $subject = '', string $note = '', bool $send_recipient = true, bool $send_merchant = false, array $recipients = []) { - $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}"; + $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/remind"; - $this->options['json'] = $data; + $this->options['json'] = $this->getInvoiceMessagePayload($subject, $note, $recipients, $send_recipient, $send_merchant); - $this->verb = 'put'; + $this->verb = 'post'; - return $this->doPayPalRequest(); + return $this->doPayPalRequest(false); } /** - * Show details for an existing invoice. + * Cancel an existing invoice which is already sent. * * @param string $invoice_id - * - * @throws \Throwable + * @param string $subject + * @param string $note + * @param bool $send_recipient + * @param bool $send_merchant + * @param array $recipients * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_get - */ - public function showInvoiceDetails(string $invoice_id) - { - $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}"; - - $this->verb = 'get'; - - return $this->doPayPalRequest(); - } - - /** - * Cancel an existing invoice which is already sent. - * - * @param string $invoice_id - * @param array $notes - * * @throws \Throwable * - * @return array|\Psr\Http\Message\StreamInterface|string - * * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_cancel */ - public function cancelInvoice(string $invoice_id, array $notes) + public function cancelInvoice(string $invoice_id, string $subject = '', string $note = '', bool $send_recipient = true, bool $send_merchant = false, array $recipients = []) { $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/cancel"; - $this->options['json'] = $notes; + $this->options['json'] = $this->getInvoiceMessagePayload($subject, $note, $recipients, $send_recipient, $send_merchant); $this->verb = 'post'; return $this->doPayPalRequest(false); } - /** - * Generate QR code against an existing invoice. - * - * @param string $invoice_id - * @param int $width - * @param int $height - * - * @throws \Throwable - * - * @return array|\Psr\Http\Message\StreamInterface|string - * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_generate-qr-code - */ - public function generateQRCodeInvoice(string $invoice_id, int $width = 100, int $height = 100) - { - $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/generate-qr-code"; - - $this->options['json'] = [ - 'width' => $width, - 'height' => $height, - ]; - $this->verb = 'post'; - - return $this->doPayPalRequest(); - } - /** * Register payment against an existing invoice. * @@ -230,7 +181,7 @@ public function registerPaymentInvoice(string $invoice_id, string $payment_date, * * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_payments-delete */ - public function deleteExternalPaymentInvoice($invoice_id, $transaction_id) + public function deleteExternalPaymentInvoice(string $invoice_id, string $transaction_id) { $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/payments/{$transaction_id}"; @@ -253,7 +204,7 @@ public function deleteExternalPaymentInvoice($invoice_id, $transaction_id) * * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_refunds */ - public function refundInvoice($invoice_id, $payment_date, $payment_method, $amount) + public function refundInvoice(string $invoice_id, string $payment_date, string $payment_method, float $amount) { $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/refunds"; @@ -285,7 +236,7 @@ public function refundInvoice($invoice_id, $payment_date, $payment_method, $amou * * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_refunds-delete */ - public function deleteRefundInvoice($invoice_id, $transaction_id) + public function deleteRefundInvoice(string $invoice_id, string $transaction_id) { $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/refunds/{$transaction_id}"; @@ -295,72 +246,133 @@ public function deleteRefundInvoice($invoice_id, $transaction_id) } /** - * Send an existing invoice. + * Generate QR code against an existing invoice. * * @param string $invoice_id - * @param string $subject - * @param string $note - * @param bool $send_recipient - * @param bool $send_merchant - * @param array $recipients + * @param int $width + * @param int $height * * @throws \Throwable * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_send + * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_generate-qr-code */ - public function sendInvoice($invoice_id, $subject = '', $note = '', $send_recipient = true, $send_merchant = false, array $recipients = []) + public function generateQRCodeInvoice(string $invoice_id, int $width = 100, int $height = 100) { - $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/send"; + $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/generate-qr-code"; - $data = [ - 'subject' => !empty($subject) ? $subject : '', - 'note' => !empty($note) ? $note : '', - 'additional_recipients' => (collect($recipients)->count() > 0) ? $recipients : '', - 'send_to_recipient' => $send_recipient, - 'send_to_invoicer' => $send_merchant, + $this->options['json'] = [ + 'width' => $width, + 'height' => $height, ]; + $this->verb = 'post'; - $this->options['json'] = collect($data)->filter()->toArray(); + return $this->doPayPalRequest(); + } + + /** + * Generate the next invoice number. + * + * @throws \Throwable + * + * @return array|\Psr\Http\Message\StreamInterface|string + * + * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_generate-next-invoice-number + */ + public function generateInvoiceNumber() + { + $this->apiEndPoint = 'v2/invoicing/generate-next-invoice-number'; $this->verb = 'post'; - return $this->doPayPalRequest(false); + return $this->doPayPalRequest(); } /** - * Send reminder for an existing invoice. + * Show details for an existing invoice. * * @param string $invoice_id - * @param string $subject - * @param string $note - * @param bool $send_recipient - * @param bool $send_merchant - * @param array $recipients * * @throws \Throwable * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_remind + * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_get */ - public function sendInvoiceReminder($invoice_id, $subject = '', $note = '', $send_recipient = true, $send_merchant = false, array $recipients = []) + public function showInvoiceDetails(string $invoice_id) { - $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}/remind"; + $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}"; - $data = [ - 'subject' => !empty($subject) ? $subject : '', - 'note' => !empty($note) ? $note : '', - 'additional_recipients' => (collect($recipients)->count() > 0) ? $recipients : '', - 'send_to_recipient' => $send_recipient, - 'send_to_invoicer' => $send_merchant, - ]; + $this->verb = 'get'; - $this->options['json'] = collect($data)->filter()->toArray(); + return $this->doPayPalRequest(); + } - $this->verb = 'post'; + /** + * Update an existing invoice. + * + * @param string $invoice_id + * @param array $data + * + * @throws \Throwable + * + * @return array|\Psr\Http\Message\StreamInterface|string + * + * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_update + */ + public function updateInvoice(string $invoice_id, array $data) + { + $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}"; + + $this->options['json'] = $data; + + $this->verb = 'put'; + + return $this->doPayPalRequest(); + } + + /** + * Delete an invoice. + * + * @param string $invoice_id + * + * @throws \Throwable + * + * @return array|\Psr\Http\Message\StreamInterface|string + * + * @see https://developer.paypal.com/docs/api/invoicing/v2/#invoices_list + */ + public function deleteInvoice(string $invoice_id) + { + $this->apiEndPoint = "v2/invoicing/invoices/{$invoice_id}"; + + $this->verb = 'delete'; return $this->doPayPalRequest(false); } + + /** + * Get Invoice Message Payload. + * + * @param string $subject + * @param string $note + * @param array $recipients + * @param bool $send_recipient + * @param bool $send_merchant + * + * @return array + */ + protected function getInvoiceMessagePayload(string $subject, string $note, array $recipients, bool $send_recipient, bool $send_merchant): array + { + $data = [ + 'subject' => !empty($subject) ? $subject : '', + 'note' => !empty($note) ? $note : '', + 'additional_recipients' => (collect($recipients)->count() > 0) ? $recipients : '', + 'send_to_recipient' => $send_recipient, + 'send_to_invoicer' => $send_merchant, + ]; + + return collect($data)->filter()->toArray(); + } } diff --git a/src/Traits/PayPalAPI/InvoicesTemplates.php b/src/Traits/PayPalAPI/InvoicesTemplates.php index d50f5fd8..0eea0fa7 100644 --- a/src/Traits/PayPalAPI/InvoicesTemplates.php +++ b/src/Traits/PayPalAPI/InvoicesTemplates.php @@ -5,49 +5,49 @@ trait InvoicesTemplates { /** - * Create a new invoice template. + * Get list of invoice templates. * - * @param array $data + * @param string $fields * * @throws \Throwable * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_create + * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_list */ - public function createInvoiceTemplate(array $data) + public function listInvoiceTemplates(string $fields = 'all') { - $this->apiEndPoint = 'v2/invoicing/templates'; - - $this->options['json'] = $data; + $this->apiEndPoint = "v2/invoicing/templates?page={$this->current_page}&page_size={$this->page_size}&fields={$fields}"; - $this->verb = 'post'; + $this->verb = 'get'; return $this->doPayPalRequest(); } /** - * Get list of invoice templates. + * Create a new invoice template. * - * @param string $fields + * @param array $data * * @throws \Throwable * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_list + * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_create */ - public function listInvoiceTemplates(string $fields = 'all') + public function createInvoiceTemplate(array $data) { - $this->apiEndPoint = "v2/invoicing/templates?page={$this->current_page}&page_size={$this->page_size}&fields={$fields}"; + $this->apiEndPoint = 'v2/invoicing/templates'; - $this->verb = 'get'; + $this->options['json'] = $data; + + $this->verb = 'post'; return $this->doPayPalRequest(); } /** - * Delete an invoice template. + * Show details for an existing invoice. * * @param string $template_id * @@ -55,15 +55,15 @@ public function listInvoiceTemplates(string $fields = 'all') * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_delete + * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_get */ - public function deleteInvoiceTemplate(string $template_id) + public function showInvoiceTemplateDetails(string $template_id) { $this->apiEndPoint = "v2/invoicing/templates/{$template_id}"; - $this->verb = 'delete'; + $this->verb = 'get'; - return $this->doPayPalRequest(false); + return $this->doPayPalRequest(); } /** @@ -90,7 +90,7 @@ public function updateInvoiceTemplate(string $template_id, array $data) } /** - * Show details for an existing invoice. + * Delete an invoice template. * * @param string $template_id * @@ -98,14 +98,14 @@ public function updateInvoiceTemplate(string $template_id, array $data) * * @return array|\Psr\Http\Message\StreamInterface|string * - * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_get + * @see https://developer.paypal.com/docs/api/invoicing/v2/#templates_delete */ - public function showInvoiceTemplateDetails(string $template_id) + public function deleteInvoiceTemplate(string $template_id) { $this->apiEndPoint = "v2/invoicing/templates/{$template_id}"; - $this->verb = 'get'; + $this->verb = 'delete'; - return $this->doPayPalRequest(); + return $this->doPayPalRequest(false); } } diff --git a/tests/Feature/AdapterFeatureTest.php b/tests/Feature/AdapterFeatureTest.php index 582def21..613b9e56 100644 --- a/tests/Feature/AdapterFeatureTest.php +++ b/tests/Feature/AdapterFeatureTest.php @@ -763,7 +763,17 @@ public function it_can_cancel_an_invoice() $expectedParams = $this->cancelInvoiceParams(); - $response = $this->client->cancelInvoice('INV2-Z56S-5LLA-Q52L-CPZ5', $expectedParams); + $response = $this->client->cancelInvoice( + 'INV2-Z56S-5LLA-Q52L-CPZ5', + 'Payment due for the invoice #ABC-123', + 'Please pay before the due date to avoid incurring late payment charges which will be adjusted in the next bill generated.', + true, + true, + [ + 'customer-a@example.com', + 'customer@example.com', + ] + ); $this->assertEmpty($response); } diff --git a/tests/Unit/Adapter/InvoicesTest.php b/tests/Unit/Adapter/InvoicesTest.php index 02171309..e0829bdd 100644 --- a/tests/Unit/Adapter/InvoicesTest.php +++ b/tests/Unit/Adapter/InvoicesTest.php @@ -121,7 +121,17 @@ public function it_can_cancel_an_invoice() $mockClient->setApiCredentials($this->getMockCredentials()); $mockClient->getAccessToken(); - $this->assertEquals($expectedResponse, $mockClient->{$expectedMethod}('INV2-Z56S-5LLA-Q52L-CPZ5', $expectedParams)); + $this->assertEquals($expectedResponse, $mockClient->{$expectedMethod}( + 'INV2-Z56S-5LLA-Q52L-CPZ5', + 'Reminder: Payment due for the invoice #ABC-123', + 'Please pay before the due date to avoid incurring late payment charges which will be adjusted in the next bill generated.', + true, + true, + [ + 'customer-a@example.com', + 'customer@example.com', + ] + )); } /** @test */