From ba6d6393fe380a881d6b2839f79a8a4090051df4 Mon Sep 17 00:00:00 2001 From: tejas Date: Wed, 26 Jun 2019 19:29:00 +0530 Subject: [PATCH 1/5] PPL-170, added invoicing version 2 api. --- samples/rest/invoice_v2/GetInvoice.php | 23 + src/angelleye/PayPal/InvoicingClass.php | 1144 +++++++++++++++ .../PayPal/rest/invoice/InvoiceAPIv2.php | 1299 +++++++++++++++++ 3 files changed, 2466 insertions(+) create mode 100644 samples/rest/invoice_v2/GetInvoice.php create mode 100644 src/angelleye/PayPal/InvoicingClass.php create mode 100644 src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php diff --git a/samples/rest/invoice_v2/GetInvoice.php b/samples/rest/invoice_v2/GetInvoice.php new file mode 100644 index 00000000..b5571842 --- /dev/null +++ b/samples/rest/invoice_v2/GetInvoice.php @@ -0,0 +1,23 @@ + $sandbox, + 'ClientID' => $rest_client_id, + 'ClientSecret' => $rest_client_secret, + 'LogResults' => $log_results, + 'LogPath' => $log_path, + 'LogLevel' => $log_level +); + +$PayPal = new InvoiceAPIv2($configArray);; +$InvoiceID = 'INV2-9LG8-P8ZN-4MPN-F5PA'; //Required. The ID of the invoice for which to show details. + +$returnArray = $PayPal->GetInvoice($InvoiceID); +echo "
";
+print_r($returnArray);
+
diff --git a/src/angelleye/PayPal/InvoicingClass.php b/src/angelleye/PayPal/InvoicingClass.php
new file mode 100644
index 00000000..3821652c
--- /dev/null
+++ b/src/angelleye/PayPal/InvoicingClass.php
@@ -0,0 +1,1144 @@
+id = $id;
+        return $this;
+    }
+
+    /**
+     * The unique invoice resource identifier.
+     *
+     * @return string
+     */
+    public function getId() {
+        return $this->id;
+    }
+
+    /**
+     * Unique number that appears on the invoice. If left blank will be auto-incremented from the last number. 25 characters max.
+     *
+     * @param string $number
+     * 
+     * @return $this
+     */
+    public function setNumber($number) {
+        $this->number = $number;
+        return $this;
+    }
+
+    /**
+     * Unique number that appears on the invoice. If left blank will be auto-incremented from the last number. 25 characters max.
+     *
+     * @return string
+     */
+    public function getNumber() {
+        return $this->number;
+    }
+
+    /**
+     * The template ID used for the invoice. Useful for copy functionality.
+     *
+     * @param string $template_id
+     * 
+     * @return $this
+     */
+    public function setTemplateId($template_id) {
+        $this->template_id = $template_id;
+        return $this;
+    }
+
+    /**
+     * The template ID used for the invoice. Useful for copy functionality.
+     *
+     * @return string
+     */
+    public function getTemplateId() {
+        return $this->template_id;
+    }
+
+    /**
+     * URI of the invoice resource.
+     *
+     * @param string $uri
+     * 
+     * @return $this
+     */
+    public function setUri($uri) {
+        $this->uri = $uri;
+        return $this;
+    }
+
+    /**
+     * URI of the invoice resource.
+     *
+     * @return string
+     */
+    public function getUri() {
+        return $this->uri;
+    }
+
+    /**
+     * Status of the invoice.
+     * Valid Values: ["DRAFT", "SENT", "PAID", "MARKED_AS_PAID", "CANCELLED", "REFUNDED", "PARTIALLY_REFUNDED", "MARKED_AS_REFUNDED", "UNPAID", "PAYMENT_PENDING"]
+     *
+     * @param string $status
+     * 
+     * @return $this
+     */
+    public function setStatus($status) {
+        $this->status = $status;
+        return $this;
+    }
+
+    /**
+     * Status of the invoice.
+     *
+     * @return string
+     */
+    public function getStatus() {
+        return $this->status;
+    }
+
+    /**
+     * Information about the merchant who is sending the invoice.
+     *
+     * @param MerchantInfo $merchant_info
+     * 
+     * @return $this
+     */
+    public function setMerchantInfo($merchant_info) {
+        $this->merchant_info = $merchant_info;
+        return $this;
+    }
+
+    /**
+     * Information about the merchant who is sending the invoice.
+     *
+     * @return MerchantInfo
+     */
+    public function getMerchantInfo() {
+        return $this->merchant_info;
+    }
+
+    /**
+     * The required invoice recipient email address and any optional billing information. One recipient is supported.
+     *
+     * @param BillingInfo[] $billing_info
+     * 
+     * @return $this
+     */
+    public function setBillingInfo($billing_info) {
+        $this->billing_info = $billing_info;
+        return $this;
+    }
+
+    /**
+     * The required invoice recipient email address and any optional billing information. One recipient is supported.
+     *
+     * @return BillingInfo[]
+     */
+    public function getBillingInfo() {
+        return $this->billing_info;
+    }
+
+    /**
+     * Append BillingInfo to the list.
+     *
+     * @param BillingInfo $billingInfo
+     * @return $this
+     */
+    public function addBillingInfo($billingInfo) {
+        if (!$this->getBillingInfo()) {
+            return $this->setBillingInfo(array($billingInfo));
+        } else {
+            return $this->setBillingInfo(
+                            array_merge($this->getBillingInfo(), array($billingInfo))
+            );
+        }
+    }
+
+    /**
+     * Remove BillingInfo from the list.
+     *
+     * @param BillingInfo $billingInfo
+     * @return $this
+     */
+    public function removeBillingInfo($billingInfo) {
+        return $this->setBillingInfo(
+                        array_diff($this->getBillingInfo(), array($billingInfo))
+        );
+    }
+
+    /**
+     * For invoices sent by email, one or more email addresses to which to send a Cc: copy of the notification. Supports only email addresses under participant.
+     *
+     * @param Participant[] $cc_info
+     * 
+     * @return $this
+     */
+    public function setCcInfo($cc_info) {
+        $this->cc_info = $cc_info;
+        return $this;
+    }
+
+    /**
+     * For invoices sent by email, one or more email addresses to which to send a Cc: copy of the notification. Supports only email addresses under participant.
+     *
+     * @return Participant[]
+     */
+    public function getCcInfo() {
+        return $this->cc_info;
+    }
+
+    /**
+     * Append CcInfo to the list.
+     *
+     * @param Participant $participant
+     * @return $this
+     */
+    public function addCcInfo($participant) {
+        if (!$this->getCcInfo()) {
+            return $this->setCcInfo(array($participant));
+        } else {
+            return $this->setCcInfo(
+                            array_merge($this->getCcInfo(), array($participant))
+            );
+        }
+    }
+
+    /**
+     * Remove CcInfo from the list.
+     *
+     * @param Participant $participant
+     * @return $this
+     */
+    public function removeCcInfo($participant) {
+        return $this->setCcInfo(
+                        array_diff($this->getCcInfo(), array($participant))
+        );
+    }
+
+    /**
+     * The shipping information for entities to whom items are being shipped.
+     *
+     * @param ShippingInfo $shipping_info
+     * 
+     * @return $this
+     */
+    public function setShippingInfo($shipping_info) {
+        $this->shipping_info = $shipping_info;
+        return $this;
+    }
+
+    /**
+     * The shipping information for entities to whom items are being shipped.
+     *
+     * @return ShippingInfo
+     */
+    public function getShippingInfo() {
+        return $this->shipping_info;
+    }
+
+    /**
+     * The list of items to include in the invoice. Maximum value is 100 items per invoice.
+     *
+     * @param InvoiceItem[] $items
+     * 
+     * @return $this
+     */
+    public function setItems($items) {
+        $this->items = $items;
+        return $this;
+    }
+
+    /**
+     * The list of items to include in the invoice. Maximum value is 100 items per invoice.
+     *
+     * @return InvoiceItem[]
+     */
+    public function getItems() {
+        return $this->items;
+    }
+
+    /**
+     * Append Items to the list.
+     *
+     * @param InvoiceItem $invoiceItem
+     * @return $this
+     */
+    public function addItem($invoiceItem) {
+        if (!$this->getItems()) {
+            return $this->setItems(array($invoiceItem));
+        } else {
+            return $this->setItems(
+                            array_merge($this->getItems(), array($invoiceItem))
+            );
+        }
+    }
+
+    /**
+     * Remove Items from the list.
+     *
+     * @param InvoiceItem $invoiceItem
+     * @return $this
+     */
+    public function removeItem($invoiceItem) {
+        return $this->setItems(
+                        array_diff($this->getItems(), array($invoiceItem))
+        );
+    }
+
+    /**
+     * The date when the invoice was enabled. The date format is *yyyy*-*MM*-*dd* *z* as defined in [Internet Date/Time Format](http://tools.ietf.org/html/rfc3339#section-5.6).
+     *
+     * @param string $invoice_date
+     * 
+     * @return $this
+     */
+    public function setInvoiceDate($invoice_date) {
+        $this->invoice_date = $invoice_date;
+        return $this;
+    }
+
+    /**
+     * The date when the invoice was enabled. The date format is *yyyy*-*MM*-*dd* *z* as defined in [Internet Date/Time Format](http://tools.ietf.org/html/rfc3339#section-5.6).
+     *
+     * @return string
+     */
+    public function getInvoiceDate() {
+        return $this->invoice_date;
+    }
+
+    /**
+     * Optional. The payment deadline for the invoice. Value is either `term_type` or `due_date` but not both.
+     *
+     * @param PaymentTerm $payment_term
+     * 
+     * @return $this
+     */
+    public function setPaymentTerm($payment_term) {
+        $this->payment_term = $payment_term;
+        return $this;
+    }
+
+    /**
+     * Optional. The payment deadline for the invoice. Value is either `term_type` or `due_date` but not both.
+     *
+     * @return PaymentTerm
+     */
+    public function getPaymentTerm() {
+        return $this->payment_term;
+    }
+
+    /**
+     * Reference data, such as PO number, to add to the invoice. Maximum length is 60 characters.
+     *
+     * @param string $reference
+     * 
+     * @return $this
+     */
+    public function setReference($reference) {
+        $this->reference = $reference;
+        return $this;
+    }
+
+    /**
+     * Reference data, such as PO number, to add to the invoice. Maximum length is 60 characters.
+     *
+     * @return string
+     */
+    public function getReference() {
+        return $this->reference;
+    }
+
+    /**
+     * The invoice level discount, as a percent or an amount value.
+     *
+     * @param Cost $discount
+     * 
+     * @return $this
+     */
+    public function setDiscount($discount) {
+        $this->discount = $discount;
+        return $this;
+    }
+
+    /**
+     * The invoice level discount, as a percent or an amount value.
+     *
+     * @return Cost
+     */
+    public function getDiscount() {
+        return $this->discount;
+    }
+
+    /**
+     * The shipping cost, as a percent or an amount value.
+     *
+     * @param ShippingCost $shipping_cost
+     * 
+     * @return $this
+     */
+    public function setShippingCost($shipping_cost) {
+        $this->shipping_cost = $shipping_cost;
+        return $this;
+    }
+
+    /**
+     * The shipping cost, as a percent or an amount value.
+     *
+     * @return ShippingCost
+     */
+    public function getShippingCost() {
+        return $this->shipping_cost;
+    }
+
+    /**
+     * The custom amount to apply on an invoice. If you include a label, the amount cannot be empty.
+     *
+     * @param CustomAmount $custom
+     * 
+     * @return $this
+     */
+    public function setCustom($custom) {
+        $this->custom = $custom;
+        return $this;
+    }
+
+    /**
+     * The custom amount to apply on an invoice. If you include a label, the amount cannot be empty.
+     *
+     * @return CustomAmount
+     */
+    public function getCustom() {
+        return $this->custom;
+    }
+
+    /**
+     * Indicates whether the invoice allows a partial payment. If set to `false`, invoice must be paid in full. If set to `true`, the invoice allows partial payments. Default is `false`.
+     *
+     * @param bool $allow_partial_payment
+     * 
+     * @return $this
+     */
+    public function setAllowPartialPayment($allow_partial_payment) {
+        $this->allow_partial_payment = $allow_partial_payment;
+        return $this;
+    }
+
+    /**
+     * Indicates whether the invoice allows a partial payment. If set to `false`, invoice must be paid in full. If set to `true`, the invoice allows partial payments. Default is `false`.
+     *
+     * @return bool
+     */
+    public function getAllowPartialPayment() {
+        return $this->allow_partial_payment;
+    }
+
+    /**
+     * If `allow_partial_payment` is set to `true`, the minimum amount allowed for a partial payment.
+     *
+     * @param Currency $minimum_amount_due
+     * 
+     * @return $this
+     */
+    public function setMinimumAmountDue($minimum_amount_due) {
+        $this->minimum_amount_due = $minimum_amount_due;
+        return $this;
+    }
+
+    /**
+     * If `allow_partial_payment` is set to `true`, the minimum amount allowed for a partial payment.
+     *
+     * @return Currency
+     */
+    public function getMinimumAmountDue() {
+        return $this->minimum_amount_due;
+    }
+
+    /**
+     * Indicates whether tax is calculated before or after a discount. If set to `false`, the tax is calculated before a discount. If set to `true`, the tax is calculated after a discount. Default is `false`.
+     *
+     * @param bool $tax_calculated_after_discount
+     * 
+     * @return $this
+     */
+    public function setTaxCalculatedAfterDiscount($tax_calculated_after_discount) {
+        $this->tax_calculated_after_discount = $tax_calculated_after_discount;
+        return $this;
+    }
+
+    /**
+     * Indicates whether tax is calculated before or after a discount. If set to `false`, the tax is calculated before a discount. If set to `true`, the tax is calculated after a discount. Default is `false`.
+     *
+     * @return bool
+     */
+    public function getTaxCalculatedAfterDiscount() {
+        return $this->tax_calculated_after_discount;
+    }
+
+    /**
+     * Indicates whether the unit price includes tax. Default is `false`.
+     *
+     * @param bool $tax_inclusive
+     * 
+     * @return $this
+     */
+    public function setTaxInclusive($tax_inclusive) {
+        $this->tax_inclusive = $tax_inclusive;
+        return $this;
+    }
+
+    /**
+     * Indicates whether the unit price includes tax. Default is `false`.
+     *
+     * @return bool
+     */
+    public function getTaxInclusive() {
+        return $this->tax_inclusive;
+    }
+
+    /**
+     * General terms of the invoice. 4000 characters max.
+     *
+     * @param string $terms
+     * 
+     * @return $this
+     */
+    public function setTerms($terms) {
+        $this->terms = $terms;
+        return $this;
+    }
+
+    /**
+     * General terms of the invoice. 4000 characters max.
+     *
+     * @return string
+     */
+    public function getTerms() {
+        return $this->terms;
+    }
+
+    /**
+     * Note to the payer. 4000 characters max.
+     *
+     * @param string $note
+     * 
+     * @return $this
+     */
+    public function setNote($note) {
+        $this->note = $note;
+        return $this;
+    }
+
+    /**
+     * Note to the payer. 4000 characters max.
+     *
+     * @return string
+     */
+    public function getNote() {
+        return $this->note;
+    }
+
+    /**
+     * A private bookkeeping memo for the merchant. Maximum length is 150 characters.
+     *
+     * @param string $merchant_memo
+     * 
+     * @return $this
+     */
+    public function setMerchantMemo($merchant_memo) {
+        $this->merchant_memo = $merchant_memo;
+        return $this;
+    }
+
+    /**
+     * A private bookkeeping memo for the merchant. Maximum length is 150 characters.
+     *
+     * @return string
+     */
+    public function getMerchantMemo() {
+        return $this->merchant_memo;
+    }
+
+    /**
+     * Full URL of an external image to use as the logo. Maximum length is 4000 characters.
+     *
+     * @param string $logo_url
+     * @throws InvalidArgumentException
+     * @return $this
+     */
+    public function setLogoUrl($logo_url) {
+        UrlValidator::validate($logo_url, "LogoUrl");
+        $this->logo_url = $logo_url;
+        return $this;
+    }
+
+    /**
+     * Full URL of an external image to use as the logo. Maximum length is 4000 characters.
+     *
+     * @return string
+     */
+    public function getLogoUrl() {
+        return $this->logo_url;
+    }
+
+    /**
+     * The total amount of the invoice.
+     *
+     * @param Currency $total_amount
+     * 
+     * @return $this
+     */
+    public function setTotalAmount($total_amount) {
+        $this->total_amount = $total_amount;
+        return $this;
+    }
+
+    /**
+     * The total amount of the invoice.
+     *
+     * @return Currency
+     */
+    public function getTotalAmount() {
+        return $this->total_amount;
+    }
+
+    /**
+     * List of payment details for the invoice.
+     *
+     * @param PaymentDetail[] $payments
+     * 
+     * @return $this
+     */
+    public function setPayments($payments) {
+        $this->payments = $payments;
+        return $this;
+    }
+
+    /**
+     * List of payment details for the invoice.
+     *
+     * @return PaymentDetail[]
+     */
+    public function getPayments() {
+        return $this->payments;
+    }
+
+    /**
+     * Append Payments to the list.
+     *
+     * @param PaymentDetail $paymentDetail
+     * @return $this
+     */
+    public function addPayment($paymentDetail) {
+        if (!$this->getPayments()) {
+            return $this->setPayments(array($paymentDetail));
+        } else {
+            return $this->setPayments(
+                            array_merge($this->getPayments(), array($paymentDetail))
+            );
+        }
+    }
+
+    /**
+     * Remove Payments from the list.
+     *
+     * @param PaymentDetail $paymentDetail
+     * @return $this
+     */
+    public function removePayment($paymentDetail) {
+        return $this->setPayments(
+                        array_diff($this->getPayments(), array($paymentDetail))
+        );
+    }
+
+    /**
+     * List of refund details for the invoice.
+     *
+     * @param RefundDetail[] $refunds
+     * 
+     * @return $this
+     */
+    public function setRefunds($refunds) {
+        $this->refunds = $refunds;
+        return $this;
+    }
+
+    /**
+     * List of refund details for the invoice.
+     *
+     * @return RefundDetail[]
+     */
+    public function getRefunds() {
+        return $this->refunds;
+    }
+
+    /**
+     * Append Refunds to the list.
+     *
+     * @param RefundDetail $refundDetail
+     * @return $this
+     */
+    public function addRefund($refundDetail) {
+        if (!$this->getRefunds()) {
+            return $this->setRefunds(array($refundDetail));
+        } else {
+            return $this->setRefunds(
+                            array_merge($this->getRefunds(), array($refundDetail))
+            );
+        }
+    }
+
+    /**
+     * Remove Refunds from the list.
+     *
+     * @param RefundDetail $refundDetail
+     * @return $this
+     */
+    public function removeRefund($refundDetail) {
+        return $this->setRefunds(
+                        array_diff($this->getRefunds(), array($refundDetail))
+        );
+    }
+
+    /**
+     * Audit information for the invoice.
+     *
+     * @param Metadata $metadata
+     * 
+     * @return $this
+     */
+    public function setMetadata($metadata) {
+        $this->metadata = $metadata;
+        return $this;
+    }
+
+    /**
+     * Audit information for the invoice.
+     *
+     * @return Metadata
+     */
+    public function getMetadata() {
+        return $this->metadata;
+    }
+
+    /**
+     * Any miscellaneous invoice data. Maximum length is 4000 characters.
+     * @deprecated Not publicly available
+     * @param string $additional_data
+     * 
+     * @return $this
+     */
+    public function setAdditionalData($additional_data) {
+        $this->additional_data = $additional_data;
+        return $this;
+    }
+
+    /**
+     * Any miscellaneous invoice data. Maximum length is 4000 characters.
+     * @deprecated Not publicly available
+     * @return string
+     */
+    public function getAdditionalData() {
+        return $this->additional_data;
+    }
+
+    /**
+     * Payment summary of the invoice including amount paid through PayPal and other sources.
+     *
+     * @param PaymentSummary $paid_amount
+     * 
+     * @return $this
+     */
+    public function setPaidAmount($paid_amount) {
+        $this->paid_amount = $paid_amount;
+        return $this;
+    }
+
+    /**
+     * Payment summary of the invoice including amount paid through PayPal and other sources.
+     *
+     * @return PaymentSummary
+     */
+    public function getPaidAmount() {
+        return $this->paid_amount;
+    }
+
+    /**
+     * Payment summary of the invoice including amount refunded through PayPal and other sources.
+     *
+     * @param PaymentSummary $refunded_amount
+     * 
+     * @return $this
+     */
+    public function setRefundedAmount($refunded_amount) {
+        $this->refunded_amount = $refunded_amount;
+        return $this;
+    }
+
+    /**
+     * Payment summary of the invoice including amount refunded through PayPal and other sources.
+     *
+     * @return PaymentSummary
+     */
+    public function getRefundedAmount() {
+        return $this->refunded_amount;
+    }
+
+    /**
+     * List of files attached to the invoice.
+     *
+     * @param FileAttachment[] $attachments
+     * 
+     * @return $this
+     */
+    public function setAttachments($attachments) {
+        $this->attachments = $attachments;
+        return $this;
+    }
+
+    /**
+     * List of files attached to the invoice.
+     *
+     * @return FileAttachment[]
+     */
+    public function getAttachments() {
+        return $this->attachments;
+    }
+
+    /**
+     * Append Attachments to the list.
+     *
+     * @param FileAttachment $fileAttachment
+     * @return $this
+     */
+    public function addAttachment($fileAttachment) {
+        if (!$this->getAttachments()) {
+            return $this->setAttachments(array($fileAttachment));
+        } else {
+            return $this->setAttachments(
+                            array_merge($this->getAttachments(), array($fileAttachment))
+            );
+        }
+    }
+
+    /**
+     * Remove Attachments from the list.
+     *
+     * @param FileAttachment $fileAttachment
+     * @return $this
+     */
+    public function removeAttachment($fileAttachment) {
+        return $this->setAttachments(
+                        array_diff($this->getAttachments(), array($fileAttachment))
+        );
+    }
+
+    /**
+     * Creates an invoice. Include invoice details including merchant information in the request.
+     *
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return Invoice
+     */
+    public function create($apiContext = null, $restCall = null) {       
+        $payLoad = $this->toJSON();      
+        $json = self::executeCall(
+            "/v2/invoicing/invoices",
+            "POST",
+            $payLoad,
+            null,
+            $apiContext,
+            $restCall
+        );
+        $this->fromJson($json);
+        return $this;
+    }
+
+    /**
+     * Searches for an invoice or invoices. Include a search object that specifies your search criteria in the request.
+     *
+     * @param Search $search
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return InvoiceSearchResponse
+     */
+    public static function search($search, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($search, 'search');
+        $payLoad = $search->toJSON();
+        $json = self::executeCall(
+                        "/v2/invoicing/search", "POST", $payLoad, null, $apiContext, $restCall
+        );
+        $ret = new InvoiceSearchResponse();
+        $ret->fromJson($json);
+        return $ret;
+    }
+
+    /**
+     * Sends an invoice, by ID, to a recipient. Optionally, set the `notify_merchant` query parameter to send the merchant an invoice update notification. By default, `notify_merchant` is `true`.
+     *
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function send($apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        $payLoad = "";
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}/send", "POST", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Sends a reminder about a specific invoice, by ID, to a recipient. Include a notification object that defines the reminder subject and other details in the JSON request body.
+     *
+     * @param Notification $notification
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function remind($notification, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        ArgumentValidator::validate($notification, 'notification');
+        $payLoad = $notification->toJSON();
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}/remind", "POST", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Cancels an invoice, by ID.
+     *
+     * @param CancelNotification $cancelNotification
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function cancel($cancelNotification, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        ArgumentValidator::validate($cancelNotification, 'cancelNotification');
+        $payLoad = $cancelNotification->toJSON();
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}/cancel", "POST", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Marks the status of a specified invoice, by ID, as paid. Include a payment detail object that defines the payment method and other details in the JSON request body.
+     *
+     * @param PaymentDetail $paymentDetail
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function recordPayment($paymentDetail, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        ArgumentValidator::validate($paymentDetail, 'paymentDetail');
+        $payLoad = $paymentDetail->toJSON();
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}/record-payment", "POST", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Marks the status of a specified invoice, by ID, as refunded. Include a refund detail object that defines the refund type and other details in the JSON request body.
+     *
+     * @param RefundDetail $refundDetail
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function recordRefund($refundDetail, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        ArgumentValidator::validate($refundDetail, 'refundDetail');
+        $payLoad = $refundDetail->toJSON();
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}/record-refund", "POST", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Gets the details for a specified invoice, by ID.
+     *
+     * @param string $invoiceId
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return Invoice
+     */
+    public static function get($invoiceId, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($invoiceId, 'invoiceId');
+        $payLoad = "";
+        $json = self::executeCall(
+                        "/v2/invoicing/invoices/$invoiceId", "GET", $payLoad, null, $apiContext, $restCall
+        );
+        $ret = new Invoice();
+        $ret->fromJson($json);
+        return $ret;
+    }
+
+    /**
+     * Lists some or all merchant invoices. Filters the response by any specified optional query string parameters.
+     *
+     * @param array $params
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return InvoiceSearchResponse
+     */
+    public static function getAll($params = array(), $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($params, 'params');
+
+        $allowedParams = array(
+            'page' => 1,
+            'page_size' => 1,
+            'total_count_required' => 1
+        );
+
+        $payLoad = "";
+        $json = self::executeCall(
+                        "/v2/invoicing/invoices/?" . http_build_query(array_intersect_key($params, $allowedParams)), "GET", $payLoad, null, $apiContext, $restCall
+        );
+        $ret = new InvoiceSearchResponse();
+        $ret->fromJson($json);
+        return $ret;
+    }
+
+    /**
+     * Fully updates an invoice by passing the invoice ID to the request URI. In addition, pass a complete invoice object in the request JSON. Partial updates are not supported.
+     *
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return Invoice
+     */
+    public function update($apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        $payLoad = $this->toJSON();
+        $json = self::executeCall(
+                        "/v2/invoicing/invoices/{$this->getId()}", "PUT", $payLoad, null, $apiContext, $restCall
+        );
+        $this->fromJson($json);
+        return $this;
+    }
+
+    /**
+     * Delete a particular invoice by passing the invoice ID to the request URI.
+     *
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function delete($apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        $payLoad = "";
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}", "DELETE", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Delete external payment.
+     *
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function deleteExternalPayment($transactionId, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        ArgumentValidator::validate($transactionId, "TransactionId");
+        $payLoad = "";
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}/payment-records/{$transactionId}", "DELETE", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Delete external refund.
+     *
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return bool
+     */
+    public function deleteExternalRefund($transactionId, $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($this->getId(), "Id");
+        ArgumentValidator::validate($transactionId, "TransactionId");
+        $payLoad = "";
+        self::executeCall(
+                "/v2/invoicing/invoices/{$this->getId()}/refund-records/{$transactionId}", "DELETE", $payLoad, null, $apiContext, $restCall
+        );
+        return true;
+    }
+
+    /**
+     * Generate a QR code for an invoice by passing the invoice ID to the request URI. The request generates a QR code that is 500 pixels in width and height. You can change the dimensions of the returned code by specifying optional query parameters.
+     *
+     * @param array $params
+     * @param string $invoiceId
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return Image
+     */
+    public static function qrCode($invoiceId, $params = array(), $apiContext = null, $restCall = null) {
+        ArgumentValidator::validate($invoiceId, 'invoiceId');
+        ArgumentValidator::validate($params, 'params');
+
+        $allowedParams = array(
+            'width' => 1,
+            'height' => 1,
+            'action' => 1
+        );
+
+        $payLoad = "";
+        $json = self::executeCall(
+                        "/v2/invoicing/invoices/$invoiceId/qr-code?" . http_build_query(array_intersect_key($params, $allowedParams)), "GET", $payLoad, null, $apiContext, $restCall
+        );
+        $ret = new Image();
+        $ret->fromJson($json);
+        return $ret;
+    }
+
+    /**
+     * Generates the successive invoice number.
+     *
+     * @param ApiContext $apiContext is the APIContext for this call. It can be used to pass dynamic configuration and credentials.
+     * @param PayPalRestCall $restCall is the Rest Call Service that is used to make rest calls
+     * @return InvoiceNumber
+     */
+    public static function generateNumber($apiContext = null, $restCall = null) {
+        $payLoad = "";
+        $json = self::executeCall(
+                        "/v2/invoicing/generate-next-invoice-number", "POST", $payLoad, null, $apiContext, $restCall
+        );
+        $ret = new InvoiceNumber();
+        $ret->fromJson($json);
+        return $ret;
+    }
+
+}
diff --git a/src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php b/src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php
new file mode 100644
index 00000000..a968a0ab
--- /dev/null
+++ b/src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php
@@ -0,0 +1,1299 @@
+
+ *
+ * @package			paypal-php-library
+ * @author			Andrew Angell 
+ * @link			https://github.com/angelleye/paypal-php-library/
+ * @website			http://www.angelleye.com
+ * @support         http://www.angelleye.com/product/premium-support/
+ * @version			v2.0.4
+ * @filesource
+ */
+
+use PayPal\Api\Address;
+use PayPal\Api\Amount;
+use PayPal\Api\BillingInfo;
+use PayPal\Api\CancelNotification;
+use PayPal\Api\Cost;
+use PayPal\Api\Currency;
+use PayPal\Api\FileAttachment;
+use PayPal\Api\Invoice;
+use PayPal\Api\InvoiceAddress;
+use PayPal\Api\InvoiceItem;
+use PayPal\Api\MerchantInfo;
+use PayPal\Api\Notification;
+use PayPal\Api\PaymentTerm;
+use PayPal\Api\PaymentDetail;
+use PayPal\Api\Phone;
+use PayPal\Api\Participant;
+use PayPal\Api\RefundDetail;
+use PayPal\Api\Search;
+use PayPal\Api\ShippingInfo;
+use PayPal\Api\ShippingCost;
+use PayPal\Api\Tax;
+use PayPal\Api\Template;
+use PayPal\Api\Templates;
+use PayPal\Api\TemplateData;
+use PayPal\Api\TemplateSettings;
+use PayPal\Api\TemplateSettingsMetadata;
+use \angelleye\PayPal\RestClass;
+use \angelleye\PayPal\InvoicingClass;
+
+/**
+ * InvoiceAPI.
+ * This class is responsible for Invoice APIs & bridge class between the REST API class and Angelleye PayPal Library.
+ *
+ * @package 		paypal-php-library
+ * @author			Andrew Angell 
+ */
+class InvoiceAPIv2 extends RestClass
+{
+
+    /**
+     * Private vairable to fetch and return @PayPal\Rest\ApiContext object.
+     *
+     * @var \PayPal\Rest\ApiContext $_api_context 
+     */
+    private $_api_context;
+
+    /**
+     * Constructor
+     *
+     * @access	public
+     * @param	mixed[]	$configArray Array structure providing config data
+     * @return	void
+     */
+    public function __construct($configArray)
+    {
+        parent::__construct($configArray);
+        $this->_api_context = $this->get_api_context();
+    }
+
+    /**
+     *  Creates an invoice. Include invoice details including merchant information in the request.
+     *
+     * @param Array $requestData
+     * @return Array|Object
+     */
+    public function CreateInvoice($requestData, $third_party = false, $refesh_token = '')
+    {
+        try {
+            $invoice = new InvoicingClass();
+
+            // ### Setting Merchant info to invoice object.
+            // ### Start
+            $MerchantInfo = new MerchantInfo();
+            if (isset($requestData['merchantInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['merchantInfo']), $MerchantInfo);
+                if (isset($requestData['merchantPhone'])) {
+                    $merchantPhone = new Phone();
+                    $this->setArrayToMethods($this->checkEmptyObject($requestData['merchantPhone']), $merchantPhone);
+                    $MerchantInfo->setPhone($merchantPhone);
+                }
+                if (isset($requestData['merchantAddress'])) {
+                    $merchantAddress = new Address();
+                    $this->setArrayToMethods($this->checkEmptyObject($requestData['merchantAddress']), $merchantAddress);
+                    $MerchantInfo->setAddress($merchantAddress);
+                }
+                $invoice->setMerchantInfo($MerchantInfo);
+            }
+            // ### End
+
+            // ### Setting cc_info
+            // ### Start
+            $Participant = new Participant();
+            if (isset($requestData['ccInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['ccInfo']), $Participant);
+                $participantArray = $this->checkEmptyObject((array)$Participant);
+                if (!empty($participantArray)) {
+                    $invoice->setCcInfo(array($Participant));
+                }
+            }
+            // ### End
+
+            // ### Setting Minimum Amount Due
+            // ### Start                            
+            $MinAmountCurrency = new Currency();
+            if (isset($requestData['MinimumAmountDue'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['MinimumAmountDue']), $MinAmountCurrency);
+            }
+            $MinAmountCurrencyArray = $this->checkEmptyObject((array)$MinAmountCurrency);
+            if (!empty($MinAmountCurrencyArray)) {
+                $invoice->setMinimumAmountDue($MinAmountCurrency);
+            }
+            // ### End
+
+            // ### Setting Billing Info to invoice object. 
+            // ### Start
+            $BillingInfo = new BillingInfo();
+            if (isset($requestData['billingInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['billingInfo']), $BillingInfo);
+            }
+            if (isset($requestData['billingInfoAddress'])) {
+                $InvoiceAddress = new InvoiceAddress();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['billingInfoAddress']), $InvoiceAddress);
+                $BillingInfo->setAddress($InvoiceAddress);
+            }
+            if (isset($requestData['billingInfoPhone'])) {
+                $billingPhone = new Phone();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['billingInfoPhone']), $billingPhone);
+                $BillingInfo->setPhone($billingPhone);
+            }
+
+            $BillingInfoArray = $this->checkEmptyObject((array)$BillingInfo);
+            if (!empty($BillingInfoArray)) {
+                $invoice->setBillingInfo(array($BillingInfo));
+            }
+            //End
+
+            // ### Add items in Invoice object.
+            // ### Start.    
+            if (isset($requestData['itemArray'])) {
+                $itemArray = array();
+                foreach ($requestData['itemArray'] as $item) {
+                    $InvoiceItem = new InvoiceItem();
+
+                    if (isset($item['UnitPrice']) && count(array_filter($item['UnitPrice'])) > 0) {
+                        $ItemCurrency = new Currency();
+                        $this->setArrayToMethods(array_filter($item['UnitPrice']), $ItemCurrency);
+                        $InvoiceItem->unit_amount = $ItemCurrency;
+                    }
+                    unset($item['UnitPrice']);
+                    if (isset($item['Tax']) && count(array_filter($item['Tax'])) > 0) {
+                        $ItemTax = new Tax();
+                        $this->setArrayToMethods(array_filter($item['Tax']), $ItemTax);
+                        $InvoiceItem->setTax($ItemTax);
+                    }
+                    unset($item['Tax']);
+                    if (isset($item['Discount']) && count(array_filter($item['Discount'])) > 0) {
+                        $ItemCost = new Cost();
+                        $this->setArrayToMethods(array_filter($item['Discount']), $ItemCost);
+                        $InvoiceItem->setDiscount($ItemCost);
+                    }
+                    unset($item['Discount']);
+
+                    $this->setArrayToMethods(array_filter($item), $InvoiceItem);
+                    array_push($itemArray, $InvoiceItem);
+                }
+                $itemArrayData = $this->checkEmptyObject($itemArray);
+                if (!empty($itemArrayData)) {
+                    $invoice->setItems($itemArray);
+                }
+            }
+            // ### END
+
+            // #### Final Discount
+            // You can add final discount to the invoice as shown below. You could either use "percent" or "value" when providing the discount
+
+            if (isset($requestData['finalDiscountForInvoice']) && $requestData['finalDiscountForInvoice']['type']  == 'Percent') {
+                $FinalDiscountCost = new Cost();
+                $FinalDiscountCost->setPercent($requestData['finalDiscountForInvoice']['Percent']);
+                $invoice->setDiscount($FinalDiscountCost);
+            }
+            if (isset($requestData['finalDiscountForInvoice']) && $requestData['finalDiscountForInvoice']['type']  == 'Amount') {
+                $FinalDiscountCost = new Cost();
+                $discountCurrency = new Currency();
+                $discountCurrency->setCurrency($requestData['finalDiscountForInvoice']['Amount']['Currency']);
+                $discountCurrency->setValue($requestData['finalDiscountForInvoice']['Amount']['Value']);
+                $FinalDiscountCost->setAmount($discountCurrency);
+                $invoice->setDiscount($FinalDiscountCost);
+            }
+
+            if (isset($requestData['paymentTerm']) && count(array_filter($requestData['paymentTerm'])) > 0) {
+                $PaymentTerm = new PaymentTerm();
+                $this->setArrayToMethods(array_filter($requestData['paymentTerm']), $PaymentTerm);
+                $invoice->setPaymentTerm($PaymentTerm);
+            }
+
+            // ### Shipping Information
+            // ### Start
+            $ShippingInfo = new ShippingInfo();
+            if (isset($requestData['shippingInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['shippingInfo']), $ShippingInfo);
+            }
+            if (isset($requestData['shippingInfoPhone'])) {
+                $ShippingInfoPhone = new Phone();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['shippingInfoPhone']), $ShippingInfoPhone);
+                $ShippingInfo->setPhone($ShippingInfoPhone);
+            }
+            if (isset($requestData['shippingInfoAddress'])) {
+                $ShippingInfoInvoiceAddress = new InvoiceAddress();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['shippingInfoAddress']), $ShippingInfoInvoiceAddress);
+                $ShippingInfo->setAddress($ShippingInfoInvoiceAddress);
+            }
+
+            $shippingInfoArray = $this->checkEmptyObject((array)$ShippingInfo);
+            if (!empty($shippingInfoArray)) {
+                $invoice->setShippingInfo($ShippingInfo);
+            }
+            if (isset($requestData['invoiceData'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['invoiceData']), $invoice);
+            }
+
+            if (isset($requestData['shippingCost']['type']) && $requestData['shippingCost']['type'] == 'Amount') {
+                $shippingCurrency = new Currency();
+                $shippingCurrency->setCurrency($requestData['shippingCost']['Amount']['Currency']);
+                $shippingCurrency->setValue($requestData['shippingCost']['Amount']['Value']);
+                $ShippingCost = new ShippingCost();
+                $ShippingCost->setAmount($shippingCurrency);
+                $invoice->setShippingCost($ShippingCost);
+            }
+
+
+            if (isset($requestData['attachments']) && count(array_filter($requestData['attachments'])) > 0) {
+                foreach ($requestData['attachments'] as $value) {
+                    $attachment = new FileAttachment();
+                    $attachment->setName($value['Name']);
+                    $attachment->setUrl($value['url']);
+                    $invoice->setAttachments(array($attachment));
+                }
+            }
+            echo '
';
+            print_r($invoice);
+            exit;
+            // ### Create Invoice
+            // Create an invoice by calling the invoice->create() method
+            if ($third_party === true  && !empty($refesh_token)) {
+                $invoice->updateAccessToken($refesh_token, $this->_api_context);
+            }
+            $requestArray = clone $invoice;
+            $invoice->create($this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICE'] = $invoice->toArray();
+            $returnArray['RAWREQUEST'] = $requestArray->toJSON();
+            $returnArray['RAWRESPONSE'] = $invoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Lists some or all merchant invoices. Filters the response by any specified optional query string parameters.
+     *
+     * @param Array $params
+     * @return Array|Object
+     */
+    public function ListInvoice($params, $third_party = false, $refesh_token = '')
+    {
+        try {
+            $apiContext = $this->_api_context;
+            if ($third_party === true  && !empty($refesh_token)) {
+                $apiContext->getCredential()->updateAccessToken($apiContext->getConfig(), $refesh_token);
+            }
+            $invoices = InvoicingClass::getAll(array_filter($params), $this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICES'] = $invoices->toArray();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Gets the details for a specified invoice, by ID.
+     *
+     * @param string $invoiceId
+     * @return Array|Object
+     */
+    public function GetInvoice($invoiceId)
+    {
+        try {
+            $invoice = InvoicingClass::get($invoiceId, $this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICE'] = $invoice->toArray();
+            $returnArray['RAWREQUEST'] = '{id:' . $invoiceId . '}';
+            $returnArray['RAWRESPONSE'] = $invoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Creates third party invoice on someone else's behalf.
+     * This requires using `Obtain User's Consent` to fetch the refresh token of the third party merchant.     
+     *  
+     * @param string $invoiceId
+     * @param string $refreshToken
+     * @return Array|Object
+     */
+    public function GetThirdPartyInvoice($invoiceId, $refreshToken)
+    {
+        try {
+            $apiContext = $this->_api_context;
+            $apiContext->getCredential()->updateAccessToken($apiContext->getConfig(), $refreshToken);
+            $invoice = InvoicingClass::get($invoiceId, $apiContext);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICE'] = $invoice->toArray();
+            $returnArray['RAWREQUEST'] = '{id:' . $invoiceId . '}';
+            $returnArray['RAWRESPONSE'] = $invoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Cancels an invoice, by ID.
+     *
+     * @param Array $cancelNotification
+     * @param string $InvoiceID
+     * @return boolean
+     */
+    public function CancelInvoice($cancelNotification, $InvoiceID, $third_party = false, $refesh_token = '')
+    {
+        try {
+            $notify = new CancelNotification();
+            $this->setArrayToMethods(array_filter($cancelNotification), $notify);
+
+            $invoice = new InvoicingClass();
+            $invoice->setId($InvoiceID);
+            if ($third_party === true  && !empty($refesh_token)) {
+                $invoice->updateAccessToken($refesh_token, $this->_api_context);
+            }
+            $requestArray = clone $invoice;
+            $cancelStatus = $invoice->cancel($notify, $this->_api_context);
+
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['CANCEL_STATUS'] = $cancelStatus;
+            $returnArray['RAWREQUEST'] = $requestArray;
+            $returnArray['RAWRESPONSE'] = $cancelStatus;
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Marks the status of a specified invoice, by ID, as refunded.
+     *
+     * @param Array $requestData
+     * @return Array|Object
+     */
+    public function RecordRefund($requestData, $third_party = false, $refesh_token = '')
+    {
+        try {
+            $invoice  = new InvoicingClass();
+            $invoice->setId($requestData['invoiceId']);
+            if ($third_party === true  && !empty($refesh_token)) {
+                $invoice->updateAccessToken($refesh_token, $this->_api_context);
+            }
+            $refund = new RefundDetail();
+            if (isset($requestData['refundDetail'])) {
+                $this->setArrayToMethods($requestData['refundDetail'], $refund);
+            }
+
+            if (isset($requestData['amount']) && count(array_filter($requestData['amount'])) > 0) {
+                $amt = new Currency(json_encode($requestData['amount']));
+                $refund->setAmount($amt);
+            }
+            $requestArray = clone $invoice;
+            $refundStatus = $invoice->recordRefund($refund, $this->_api_context);
+            $invoice = InvoicingClass::get($requestData['invoiceId'], $this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['REFUND_STATUS'] = $refundStatus;
+            $returnArray['INVOICE'] = $invoice->toArray();
+            $returnArray['RAWREQUEST'] = $requestArray;
+            $returnArray['RAWRESPONSE'] = $invoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Sends a reminder to the payer about an invoice, by ID.
+     *
+     * @param Array $remindNotification
+     * @param string $InvoiceID
+     * @return Array|Object
+     */
+    public function RemindInvoice($remindNotification, $InvoiceID, $third_party = false, $refesh_token = '')
+    {
+        try {
+            $apiContext = $this->_api_context;
+            if ($third_party === true  && !empty($refesh_token)) {
+                $apiContext->getCredential()->updateAccessToken($apiContext->getConfig(), $refesh_token);
+            }
+            $invoice  = new InvoicingClass();
+            $invoice->setId($InvoiceID);
+            $notify = new Notification();
+            $this->setArrayToMethods(array_filter($remindNotification), $notify);
+            $remindStatus = $invoice->remind($notify, $apiContext);
+            $requestArray = clone $invoice;
+            $invoice = InvoicingClass::get($InvoiceID, $apiContext);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['REMIND_STATUS'] = $remindStatus;
+            $returnArray['REMIND_INVOICE'] = $invoice->toArray();
+            $returnArray['RAWREQUEST'] = $requestArray;
+            $returnArray['RAWRESPONSE'] = $invoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Generate a QR code for an invoice by passing the invoice ID.
+     *
+     * @param Array $parameters
+     * @param string $InvoiceID
+     * @param string $path
+     * @return Array|Object
+     */
+    public function RetrieveQRCode($parameters, $InvoiceID, $path, $third_party = false, $refesh_token = '')
+    {
+
+        try {
+            $apiContext = $this->_api_context;
+            if ($third_party === true  && !empty($refesh_token)) {
+                $apiContext->getCredential()->updateAccessToken($apiContext->getConfig(), $refesh_token);
+            }
+            $image = InvoicingClass::qrCode($InvoiceID, array_filter($parameters), $apiContext);
+            $path = $image->saveToFile($path);
+            $returnArray['RESULT'] = 'Success';
+            return array('Image' => $image->getImage());
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Searches for an invoice or invoices. Include a search object that specifies your search criteria in the request.
+     *
+     * @param Array $parameters
+     * @return Array|Object
+     */
+    public function SearchInvoices($parameters, $third_party = false, $refesh_token = '')
+    {
+
+        try {
+            $apiContext = $this->_api_context;
+            if ($third_party === true  && !empty($refesh_token)) {
+                $apiContext->getCredential()->updateAccessToken($apiContext->getConfig(), $refesh_token);
+            }
+            $search = new Search(json_encode(array_filter($parameters)));
+            $invoices = InvoicingClass::search($search, $apiContext);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICES'] = $invoices->toArray();
+            $returnArray['RAWREQUEST'] = json_encode(array_filter($parameters));
+            $returnArray['RAWRESPONSE'] = $invoices->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Fully updates an invoice, by ID.
+     *
+     * @param Array|Object $requestData
+     * @return Array|Object
+     */
+    public function UpdateInvoice($requestData, $third_party = false, $refesh_token = '')
+    {
+
+        try {
+            $invoice = new InvoicingClass();
+            $invoice->setId($requestData['InvoiceID']);
+            // ### Setting Merchant info to invoice object.
+            // ### Start
+            $MerchantInfo = new MerchantInfo();
+            if (isset($requestData['merchantInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['merchantInfo']), $MerchantInfo);
+                if (isset($requestData['merchantPhone'])) {
+                    $merchantPhone = new Phone();
+                    $this->setArrayToMethods($this->checkEmptyObject($requestData['merchantPhone']), $merchantPhone);
+                    $MerchantInfo->setPhone($merchantPhone);
+                }
+                if (isset($requestData['merchantAddress'])) {
+                    $merchantAddress = new Address();
+                    $this->setArrayToMethods($this->checkEmptyObject($requestData['merchantAddress']), $merchantAddress);
+                    $MerchantInfo->setAddress($merchantAddress);
+                }
+                $invoice->setMerchantInfo($MerchantInfo);
+            }
+            // ### End
+
+            // ### Setting cc_info
+            // ### Start
+            $Participant = new Participant();
+            if (isset($requestData['ccInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['ccInfo']), $Participant);
+                $participantArray = $this->checkEmptyObject((array)$Participant);
+                if (!empty($participantArray)) {
+                    $invoice->setCcInfo(array($Participant));
+                }
+            }
+            // ### End
+
+            // ### Setting Minimum Amount Due
+            // ### Start
+            $MinAmountCurrency = new Currency();
+            if (isset($requestData['MinimumAmountDue'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['MinimumAmountDue']), $MinAmountCurrency);
+            }
+            $MinAmountCurrencyArray = $this->checkEmptyObject((array)$MinAmountCurrency);
+            if (!empty($MinAmountCurrencyArray)) {
+                $invoice->setMinimumAmountDue($MinAmountCurrency);
+            }
+            // ### End
+
+            // ### Setting Billing Info to invoice object.
+            // ### Start
+            $BillingInfo = new BillingInfo();
+            if (isset($requestData['billingInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['billingInfo']), $BillingInfo);
+            }
+            if (isset($requestData['billingInfoAddress'])) {
+                $InvoiceAddress = new InvoiceAddress();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['billingInfoAddress']), $InvoiceAddress);
+                $BillingInfo->setAddress($InvoiceAddress);
+            }
+            if (isset($requestData['billingInfoPhone'])) {
+                $billingPhone = new Phone();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['billingInfoPhone']), $billingPhone);
+                $BillingInfo->setPhone($billingPhone);
+            }
+
+            $BillingInfoArray = $this->checkEmptyObject((array)$BillingInfo);
+            if (!empty($BillingInfoArray)) {
+                $invoice->setBillingInfo(array($BillingInfo));
+            }
+            //End
+
+            // ### Add items in Invoice object.
+            // ### Start.
+            if (isset($requestData['itemArray'])) {
+
+                $itemArray = array();
+                foreach ($requestData['itemArray'] as $item) {
+                    $InvoiceItem = new InvoiceItem();
+
+                    if (isset($item['UnitPrice']) && count(array_filter($item['UnitPrice'])) > 0) {
+                        $ItemCurrency = new Currency();
+                        $this->setArrayToMethods(array_filter($item['UnitPrice']), $ItemCurrency);
+                        $InvoiceItem->setUnitPrice($ItemCurrency);
+                    }
+                    unset($item['UnitPrice']);
+                    if (isset($item['Tax']) && count(array_filter($item['Tax'])) > 0) {
+                        $ItemTax = new Tax();
+                        $this->setArrayToMethods(array_filter($item['Tax']), $ItemTax);
+                        $InvoiceItem->setTax($ItemTax);
+                    }
+                    unset($item['Tax']);
+                    if (isset($item['Discount']) && count(array_filter($item['Discount'])) > 0) {
+                        $ItemCost = new Cost();
+                        $this->setArrayToMethods(array_filter($item['Discount']), $ItemCost);
+                        $InvoiceItem->setDiscount($ItemCost);
+                    }
+                    unset($item['Discount']);
+
+                    $this->setArrayToMethods(array_filter($item), $InvoiceItem);
+                    array_push($itemArray, $InvoiceItem);
+                }
+                $itemArrayData = $this->checkEmptyObject($itemArray);
+                if (!empty($itemArrayData)) {
+                    $invoice->setItems($itemArray);
+                }
+            }
+            // ### END
+
+            // #### Final Discount
+            // You can add final discount to the invoice as shown below. You could either use "percent" or "value" when providing the discount
+
+            if (isset($requestData['finalDiscountForInvoice']) && $requestData['finalDiscountForInvoice']['type']  == 'Percent') {
+                $FinalDiscountCost = new Cost();
+                $FinalDiscountCost->setPercent($requestData['finalDiscountForInvoice']['Percent']);
+                $invoice->setDiscount($FinalDiscountCost);
+            }
+            if (isset($requestData['finalDiscountForInvoice']) && $requestData['finalDiscountForInvoice']['type']  == 'Amount') {
+                $FinalDiscountCost = new Cost();
+                $discountCurrency = new Currency();
+                $discountCurrency->setCurrency($requestData['finalDiscountForInvoice']['Amount']['Currency']);
+                $discountCurrency->setValue($requestData['finalDiscountForInvoice']['Amount']['Value']);
+                $FinalDiscountCost->setAmount($discountCurrency);
+                $invoice->setDiscount($FinalDiscountCost);
+            }
+            if (isset($requestData['finalDiscountForInvoice']) && $requestData['finalDiscountForInvoice']['type']  == 'Amount') {
+                $FinalDiscountCost = new Cost();
+                $discountCurrency = new Currency();
+                $discountCurrency->setCurrency($requestData['finalDiscountForInvoice']['Amount']['Currency']);
+                $discountCurrency->setValue($requestData['finalDiscountForInvoice']['Amount']['Value']);
+                $FinalDiscountCost->setAmount($discountCurrency);
+                $invoice->setDiscount($FinalDiscountCost);
+            }
+
+            if (isset($requestData['paymentTerm']) && count(array_filter($requestData['paymentTerm'])) > 0) {
+                $PaymentTerm = new PaymentTerm();
+                $this->setArrayToMethods(array_filter($requestData['paymentTerm']), $PaymentTerm);
+                $invoice->setPaymentTerm($PaymentTerm);
+            }
+
+            // ### Shipping Information
+            // ### Start
+            $ShippingInfo = new ShippingInfo();
+            if (isset($requestData['shippingInfo'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['shippingInfo']), $ShippingInfo);
+            }
+            if (isset($requestData['shippingInfoPhone'])) {
+                $ShippingInfoPhone = new Phone();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['shippingInfoPhone']), $ShippingInfoPhone);
+                $ShippingInfo->setPhone($ShippingInfoPhone);
+            }
+            if (isset($requestData['shippingInfoAddress'])) {
+                $ShippingInfoInvoiceAddress = new InvoiceAddress();
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['shippingInfoAddress']), $ShippingInfoInvoiceAddress);
+                $ShippingInfo->setAddress($ShippingInfoInvoiceAddress);
+            }
+
+            $shippingInfoArray = $this->checkEmptyObject((array)$ShippingInfo);
+            if (!empty($shippingInfoArray)) {
+                $invoice->setShippingInfo($ShippingInfo);
+            }
+            if (isset($requestData['invoiceData'])) {
+                $this->setArrayToMethods($this->checkEmptyObject($requestData['invoiceData']), $invoice);
+            }
+
+            if (isset($requestData['shippingCost']['type']) && $requestData['shippingCost']['type'] == 'Amount') {
+                $shippingCurrency = new Currency();
+                $this->setArrayToMethods(array_filter($requestData['shippingCost']['Currency']), $shippingCurrency);
+                $ShippingCost = new ShippingCost();
+                $ShippingCost->setAmount($shippingCurrency);
+                $invoice->setShippingCost($ShippingCost);
+            }
+            if (isset($requestData['attachments']) && count(array_filter($requestData['attachments'])) > 0) {
+                foreach ($requestData['attachments'] as $key => $value) {
+                    $attachment = new FileAttachment();
+                    $attachment->setName($value['Name']);
+                    $attachment->setUrl($value['Url']);
+                    $invoice->setAttachments(array($attachment));
+                }
+            }
+            if (isset($requestData['shippingCost']['type']) && $requestData['shippingCost']['type'] == 'Amount') {
+                $shippingCurrency = new Currency();
+                $shippingCurrency->setCurrency($requestData['shippingCost']['Amount']['Currency']);
+                $shippingCurrency->setValue($requestData['shippingCost']['Amount']['Value']);
+                $ShippingCost = new ShippingCost();
+                $ShippingCost->setAmount($shippingCurrency);
+                $invoice->setShippingCost($ShippingCost);
+            }
+            $this->setArrayToMethods(array_filter($requestData['invoiceData']), $invoice);
+
+            if ($third_party === true  && !empty($refesh_token)) {
+                $invoice->updateAccessToken($refesh_token, $this->_api_context);
+            }
+            $requestArray = clone $invoice;
+            $invoice->update($this->_api_context);
+            $invoice = InvoicingClass::get($invoice->getId(), $this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICE'] = $invoice->toArray();
+            $returnArray['RAWREQUEST'] = $requestArray;
+            $returnArray['RAWRESPONSE'] = $invoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Sends an invoice, by ID, to a customer. 
+     *
+     * @param string $invoiceId
+     * @param boolean $third_party
+     * @param  string $refresh_token
+     * @return Array|Object
+     */
+    public function SendInvoice($invoiceId, $third_party = false, $refresh_token = '')
+    {
+        try {
+            $invoice = new InvoicingClass();
+            $invoice->setId($invoiceId);
+            if ($third_party === true  && !empty($refresh_token)) {
+                $invoice->updateAccessToken($refresh_token, $this->_api_context);
+            }
+            $sendStatus = $invoice->send($this->_api_context);
+            $Getinvoice = InvoicingClass::get($invoice->getId(), $this->_api_context);
+
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['SEND_STATUS'] = $sendStatus;
+            $returnArray['INVOICE'] = $Getinvoice->toArray();
+            $returnArray['RAWREQUEST'] = '{id:' . $invoiceId . '}';
+            $returnArray['RAWRESPONSE'] = $Getinvoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Deletes invoices in the DRAFT or SCHEDULED state, by ID. 
+     *
+     * @param string $invoiceId
+     * @return Array|Object
+     */
+    public function DeleteInvoice($invoiceId, $third_party = false, $refesh_token = '')
+    {
+
+        try {
+            $invoice = new InvoicingClass();
+            $invoice->setId($invoiceId);
+            if ($third_party === true  && !empty($refesh_token)) {
+                $invoice->updateAccessToken($refesh_token, $this->_api_context);
+            }
+            $deleteStatus = $invoice->delete($this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['DELETE_STATUS'] = $deleteStatus;
+            $returnArray['RAWREQUEST'] = '{id:' . $invoiceId . '}';
+            $returnArray['RAWRESPONSE'] = $deleteStatus;
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Generates the next invoice number that is available to the merchant.
+     * The next invoice number uses the prefix and suffix from the last invoice number and increments the number by one.
+     *
+     * @return Array|Object
+     */
+    public function GetNextInvoiceNumber($third_party = false, $refesh_token = '')
+    {
+        try {
+            $apiContext = $this->_api_context;
+            if ($third_party === true  && !empty($refesh_token)) {
+                $apiContext->getCredential()->updateAccessToken($apiContext->getConfig(), $refesh_token);
+            }
+            $number = InvoicingClass::generateNumber($apiContext);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICE_NUMBER'] = $number->toArray();
+            $returnArray['RAWREQUEST'] = '';
+            $returnArray['RAWRESPONSE'] = $number->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     *Marks the status of a specified invoice, by ID, as paid.
+     *
+     * @param string $invoiceId
+     * @param Array $record
+     * @param Array $amount
+     * @return Array|Object
+     */
+    public function RecordPayment($invoiceId, $record, $amount, $third_party = false, $refesh_token = '')
+    {
+        try {
+            $invoice = new InvoicingClass();
+            $invoice->setId($invoiceId);
+            if ($third_party === true  && !empty($refesh_token)) {
+                $invoice->updateAccessToken($refesh_token, $this->_api_context);
+            }
+            $PaymentDetail = new PaymentDetail();
+            $this->setArrayToMethods(array_filter($record), $PaymentDetail);
+
+            if (count(array_filter($amount)) > 0) {
+                $amt = new Currency(json_encode($amount));
+                $PaymentDetail->setAmount($amt);
+            }
+
+            $recordStatus = $invoice->recordPayment($PaymentDetail, $this->_api_context);
+
+            $returnInvoice = InvoicingClass::get($invoiceId, $this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['RECORD_STATUS'] = $recordStatus;
+            $returnArray['INVOICE'] = $returnInvoice->toArray();
+            $returnArray['RAWREQUEST'] = '{id:' . $invoiceId . '}';
+            $returnArray['RAWRESPONSE'] = $returnInvoice->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Creates an invoice template.
+     *
+     * @param Array $requestData
+     * @return Array|Object
+     */
+    public function CreateInvoiceTemplate($requestData)
+    {
+
+        try {
+            $invoiceTemplateData = new TemplateData();
+
+            /**
+             * Setting Items in Invoice Template
+             */
+            if (isset($requestData['InvoiceItemArray'])) {
+                $itemArray = array();
+
+                foreach ($requestData['InvoiceItemArray'] as $item) {
+                    $InvoiceItem = new InvoiceItem();
+
+                    if (isset($item['UnitPrice']) && count(array_filter($item['UnitPrice'])) > 0) {
+                        $ItemCurrency = new Currency();
+                        $this->setArrayToMethods(array_filter($item['UnitPrice']), $ItemCurrency);
+                        $InvoiceItem->setUnitPrice($ItemCurrency);
+                    }
+                    unset($item['UnitPrice']);
+
+                    if (isset($item['Tax']) && count(array_filter($item['Tax'])) > 0) {
+                        $ItemTax = new Tax();
+                        $this->setArrayToMethods(array_filter($item['Tax']), $ItemTax);
+                        $InvoiceItem->setTax($ItemTax);
+                    }
+                    unset($item['Tax']);
+
+                    if (isset($item['Discount']) && count(array_filter($item['Discount'])) > 0) {
+                        $ItemCost = new Cost();
+                        $this->setArrayToMethods(array_filter($item['Discount']), $ItemCost);
+                        $InvoiceItem->setDiscount($ItemCost);
+                    }
+                    unset($item['Discount']);
+
+                    if (count(array_filter($item)) > 0) {
+                        $this->setArrayToMethods(array_filter($item), $InvoiceItem);
+                        array_push($itemArray, $InvoiceItem);
+                        $invoiceTemplateData->addItem($InvoiceItem);
+                    }
+                }
+            }
+
+
+            // ### Setting Merchant info to invoice template object.
+            // ### Start
+            if (isset($requestData['merchantInfo'])) {
+                $MerchantInfo = new MerchantInfo();
+                if (isset($requestData['merchantInfo']) && count(array_filter($requestData['merchantInfo'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['merchantInfo']), $MerchantInfo);
+                }
+                $merchantPhone = new Phone();
+                if (isset($requestData['merchantPhone']) && count(array_filter($requestData['merchantPhone'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['merchantPhone']), $merchantPhone);
+                    $MerchantInfo->setPhone($merchantPhone);
+                }
+                $merchantAddress = new Address();
+                if (isset($requestData['merchantAddress']) && count(array_filter($requestData['merchantAddress'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['merchantAddress']), $merchantAddress);
+                    $MerchantInfo->setAddress($merchantAddress);
+                }
+                $invoiceTemplateData->setMerchantInfo($MerchantInfo);
+            }
+
+
+
+            // ### End
+
+            // ### Setting Billing Info to invoice object. 
+            // ### Start
+
+            if (isset($requestData['billingInfo'])) {
+                $BillingInfo = new BillingInfo();
+                if (isset($requestData['billingInfo']) && count(array_filter($requestData['billingInfo'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['billingInfo']), $BillingInfo);
+                }
+
+                $InvoiceAddress = new InvoiceAddress();
+                if (isset($requestData['billingInfoAddress']) && count(array_filter($requestData['billingInfoAddress'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['billingInfoAddress']), $InvoiceAddress);
+                    $BillingInfo->setAddress($InvoiceAddress);
+                }
+
+                $billingPhone = new Phone();
+                if (count(array_filter($requestData['billingInfoPhone'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['billingInfoPhone']), $billingPhone);
+                    $BillingInfo->setPhone($billingPhone);
+                }
+                $invoiceTemplateData->setBillingInfo(array($BillingInfo));
+            }
+            //End
+
+
+            // ### Shipping Information
+            // ### Start
+
+            if (isset($requestData['shippingInfo'])) {
+                $ShippingInfo = new ShippingInfo();
+                $this->setArrayToMethods(array_filter($requestData['shippingInfo']), $ShippingInfo);
+
+                $ShippingInfoPhone = new Phone();
+                if (isset($requestData['shippingInfoPhone']) && count(array_filter($requestData['shippingInfoPhone'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['shippingInfoPhone']), $ShippingInfoPhone);
+                    $ShippingInfo->setPhone($ShippingInfoPhone);
+                }
+
+                $ShippingInfoInvoiceAddress = new InvoiceAddress();
+                if (isset($requestData['shippingInfoAddress']) && count(array_filter($requestData['shippingInfoAddress'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['shippingInfoAddress']), $ShippingInfoInvoiceAddress);
+                    $ShippingInfo->setAddress($ShippingInfoInvoiceAddress);
+                }
+                $invoiceTemplateData->setShippingInfo($ShippingInfo);
+            }
+            if (isset($requestData['templateData'])) {
+                if (isset($requestData['templateData']['MinimumAmountDue']) && count(array_filter($requestData['templateData']['MinimumAmountDue'])) > 0) {
+                    $TemplateMinimumAmountDueCurrency = new Currency();
+                    $this->setArrayToMethods(array_filter($requestData['templateData']['MinimumAmountDue']), $TemplateMinimumAmountDueCurrency);
+                    $invoiceTemplateData->setMinimumAmountDue($TemplateMinimumAmountDueCurrency);
+                }
+                unset($requestData['templateData']['MinimumAmountDue']);
+
+                if (isset($requestData['templateData']['TotalAmount']) && count(array_filter($requestData['templateData']['TotalAmount'])) > 0) {
+                    $TemplateTotalAmountCurrency = new Currency();
+                    $this->setArrayToMethods(array_filter($requestData['templateData']['TotalAmount']), $TemplateTotalAmountCurrency);
+                    $invoiceTemplateData->setTotalAmount($TemplateTotalAmountCurrency);
+                }
+                unset($requestData['templateData']['TotalAmount']);
+                $this->setArrayToMethods(array_filter($requestData['templateData']), $invoiceTemplateData);
+            }
+
+            $templateDataCcInfo = isset($requestData['TemplateDataCcInfo']) ? trim($requestData['TemplateDataCcInfo']) : '';
+            if (!empty($templateDataCcInfo)) {
+                $invoiceTemplateData->addCcInfo($templateDataCcInfo);
+            }
+
+            if (isset($requestData['templateDiscount']) && count(array_filter($requestData['templateDiscount'])) > 0) {
+                $templateDiscountCost = new Cost();
+                $this->setArrayToMethods(array_filter($requestData['templateDiscount']), $templateDiscountCost);
+                $invoiceTemplateData->setDiscount($templateDiscountCost);
+            }
+
+            if (isset($requestData['paymentTerm']) && count(array_filter($requestData['paymentTerm'])) > 0) {
+                $PaymentTerm = new PaymentTerm();
+                $this->setArrayToMethods(array_filter($requestData['paymentTerm']), $PaymentTerm);
+                $invoiceTemplateData->setPaymentTerm($PaymentTerm);
+            }
+
+            if (isset($requestData['attachments']) && count(array_filter($requestData['attachments'])) > 0) {
+                $attachment = new FileAttachment();
+                $this->setArrayToMethods(array_filter($requestData['attachments']), $attachment);
+                $invoiceTemplateData->setAttachments(array($attachment));
+            }
+
+            // ### Template Settings    
+            $displayPreferences = new TemplateSettingsMetadata();
+            if (isset($requestData['TemplateSettingsMetadata']) && count(array_filter($requestData['TemplateSettingsMetadata'])) > 0) {
+                $this->setArrayToMethods(array_filter($requestData['TemplateSettingsMetadata']), $displayPreferences);
+            }
+
+            $settingDate = new TemplateSettings();
+            if (isset($requestData['TemplateSettings']) && count(array_filter($requestData['TemplateSettings'])) > 0) {
+                $this->setArrayToMethods(array_filter($requestData['TemplateSettings']), $settingDate);
+            }
+
+            if (count(array_filter((array)$displayPreferences)) > 0) {
+                $settingDate->setDisplayPreference($displayPreferences);
+            }
+
+            // ### Template
+            $invoiceTemplate = new Template();
+            if (isset($requestData['Template']) && count(array_filter($requestData['Template'])) > 0) {
+                $this->setArrayToMethods(array_filter($requestData['Template']), $invoiceTemplate);
+            }
+
+            if (count(array_filter((array)$invoiceTemplateData)) > 0) {
+                $invoiceTemplate->setTemplateData($invoiceTemplateData);
+            }
+
+            if (count(array_filter((array)$settingDate)) > 0) {
+                $invoiceTemplate->addSetting($settingDate);
+            }
+            $requestArray = clone $invoiceTemplate;
+            $invoiceTemplate->create($this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['TEMPLATE'] = $invoiceTemplate->toArray();
+            $returnArray['RAWREQUEST'] = $requestArray->toJSON();
+            $returnArray['RAWRESPONSE'] = $invoiceTemplate->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Deletes a template, by ID.
+     *
+     * @param string $template_id
+     * @return Array|Object
+     */
+    public function DeleteInvoiceTemplate($template_id)
+    {
+        try {
+            $template = new Template();
+            $template->setTemplateId($template_id);
+            $deleteStatus = $template->delete($this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['DELETE_STATUS'] = $deleteStatus;
+            $returnArray['RAWREQUEST'] = '{id:' . $template_id . '}';
+            $returnArray['RAWRESPONSE'] = $deleteStatus;
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Lists merchant-created templates with associated details
+     *
+     * @param Array $fields
+     * @return Array|Object
+     */
+    public function GetAllInvoiceTemplates($fields)
+    {
+
+        try {
+            $templates = Templates::getAll($fields, $this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICE_TEMPLATES'] = $templates->toArray();
+            $returnArray['RAWREQUEST'] = json_encode($fields);
+            $returnArray['RAWRESPONSE'] = $templates->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Shows details for a template, by ID.
+     *
+     * @param string $templateId
+     * @return Array|Object
+     */
+    public function GetInvoiceTemplate($templateId)
+    {
+        try {
+            $template = Template::get($templateId, $this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['TEMPLATE'] = $template->toArray();
+            $returnArray['RAWREQUEST'] = '{id:' . $templateId . '}';
+            $returnArray['RAWRESPONSE'] = $template->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+
+    /**
+     * Updates a template, by ID.
+     *
+     * @param string  $templateId
+     * @param Array $requestData
+     * @return Array|Object
+     */
+    public function UpdateInvoiceTemplate($templateId, $requestData)
+    {
+        try {
+            $invoiceTemplateData = new TemplateData();
+            /**
+             * Setting Items in Invoice Template
+             */
+            if (isset($requestData['InvoiceItemArray'])) {
+                $itemArray = array();
+
+                foreach ($requestData['InvoiceItemArray'] as $item) {
+                    $InvoiceItem = new InvoiceItem();
+
+                    if (isset($item['UnitPrice']) && count(array_filter($item['UnitPrice'])) > 0) {
+                        $ItemCurrency = new Currency();
+                        $this->setArrayToMethods(array_filter($item['UnitPrice']), $ItemCurrency);
+                        $InvoiceItem->setUnitPrice($ItemCurrency);
+                    }
+                    unset($item['UnitPrice']);
+
+                    if (isset($item['Tax']) && count(array_filter($item['Tax'])) > 0) {
+                        $ItemTax = new Tax();
+                        $this->setArrayToMethods(array_filter($item['Tax']), $ItemTax);
+                        $InvoiceItem->setTax($ItemTax);
+                    }
+                    unset($item['Tax']);
+
+                    if (isset($item['Discount']) && count(array_filter($item['Discount'])) > 0) {
+                        $ItemCost = new Cost();
+                        $this->setArrayToMethods(array_filter($item['Discount']), $ItemCost);
+                        $InvoiceItem->setDiscount($ItemCost);
+                    }
+                    unset($item['Discount']);
+
+                    if (count(array_filter($item)) > 0) {
+                        $this->setArrayToMethods(array_filter($item), $InvoiceItem);
+                        array_push($itemArray, $InvoiceItem);
+                        $invoiceTemplateData->addItem($InvoiceItem);
+                    }
+                }
+            }
+
+
+            // ### Setting Merchant info to invoice template object.
+            // ### Start
+            if (isset($requestData['merchantInfo'])) {
+                $MerchantInfo = new MerchantInfo();
+                if (isset($requestData['merchantInfo']) && count(array_filter($requestData['merchantInfo'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['merchantInfo']), $MerchantInfo);
+                }
+                $merchantPhone = new Phone();
+                if (isset($requestData['merchantPhone']) && count(array_filter($requestData['merchantPhone'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['merchantPhone']), $merchantPhone);
+                    $MerchantInfo->setPhone($merchantPhone);
+                }
+                $merchantAddress = new Address();
+                if (isset($requestData['merchantAddress']) && count(array_filter($requestData['merchantAddress'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['merchantAddress']), $merchantAddress);
+                    $MerchantInfo->setAddress($merchantAddress);
+                }
+                $invoiceTemplateData->setMerchantInfo($MerchantInfo);
+            }
+
+            // ### End
+
+            // ### Setting Billing Info to invoice object.
+            // ### Start
+
+            if (isset($requestData['billingInfo'])) {
+                $BillingInfo = new BillingInfo();
+                if (isset($requestData['billingInfo']) && count(array_filter($requestData['billingInfo'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['billingInfo']), $BillingInfo);
+                }
+
+                $InvoiceAddress = new InvoiceAddress();
+                if (isset($requestData['billingInfoAddress']) && count(array_filter($requestData['billingInfoAddress'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['billingInfoAddress']), $InvoiceAddress);
+                    $BillingInfo->setAddress($InvoiceAddress);
+                }
+
+                $billingPhone = new Phone();
+                if (count(array_filter($requestData['billingInfoPhone'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['billingInfoPhone']), $billingPhone);
+                    $BillingInfo->setPhone($billingPhone);
+                }
+                $invoiceTemplateData->setBillingInfo(array($BillingInfo));
+            }
+            //End
+
+
+            // ### Shipping Information
+            // ### Start
+
+            if (isset($requestData['shippingInfo'])) {
+                $ShippingInfo = new ShippingInfo();
+                $this->setArrayToMethods(array_filter($requestData['shippingInfo']), $ShippingInfo);
+
+                $ShippingInfoPhone = new Phone();
+                if (isset($requestData['shippingInfoPhone']) && count(array_filter($requestData['shippingInfoPhone'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['shippingInfoPhone']), $ShippingInfoPhone);
+                    $ShippingInfo->setPhone($ShippingInfoPhone);
+                }
+
+                $ShippingInfoInvoiceAddress = new InvoiceAddress();
+                if (isset($requestData['shippingInfoAddress']) && count(array_filter($requestData['shippingInfoAddress'])) > 0) {
+                    $this->setArrayToMethods(array_filter($requestData['shippingInfoAddress']), $ShippingInfoInvoiceAddress);
+                    $ShippingInfo->setAddress($ShippingInfoInvoiceAddress);
+                }
+                $invoiceTemplateData->setShippingInfo($ShippingInfo);
+            }
+            if (isset($requestData['templateData'])) {
+                if (isset($requestData['templateData']['MinimumAmountDue']) && count(array_filter($requestData['templateData']['MinimumAmountDue'])) > 0) {
+                    $TemplateMinimumAmountDueCurrency = new Currency();
+                    $this->setArrayToMethods(array_filter($requestData['templateData']['MinimumAmountDue']), $TemplateMinimumAmountDueCurrency);
+                    $invoiceTemplateData->setMinimumAmountDue($TemplateMinimumAmountDueCurrency);
+                }
+                unset($requestData['templateData']['MinimumAmountDue']);
+
+                if (isset($requestData['templateData']['TotalAmount']) && count(array_filter($requestData['templateData']['TotalAmount'])) > 0) {
+                    $TemplateTotalAmountCurrency = new Currency();
+                    $this->setArrayToMethods(array_filter($requestData['templateData']['TotalAmount']), $TemplateTotalAmountCurrency);
+                    $invoiceTemplateData->setTotalAmount($TemplateTotalAmountCurrency);
+                }
+                unset($requestData['templateData']['TotalAmount']);
+                $this->setArrayToMethods(array_filter($requestData['templateData']), $invoiceTemplateData);
+            }
+
+            $templateDataCcInfo = isset($requestData['TemplateDataCcInfo']) ? trim($requestData['TemplateDataCcInfo']) : '';
+            if (!empty($templateDataCcInfo)) {
+                $invoiceTemplateData->addCcInfo($templateDataCcInfo);
+            }
+
+            if (isset($requestData['templateDiscount']) && count(array_filter($requestData['templateDiscount'])) > 0) {
+                $templateDiscountCost = new Cost();
+                $this->setArrayToMethods(array_filter($requestData['templateDiscount']), $templateDiscountCost);
+                $invoiceTemplateData->setDiscount($templateDiscountCost);
+            }
+
+            if (isset($requestData['paymentTerm']) && count(array_filter($requestData['paymentTerm'])) > 0) {
+                $PaymentTerm = new PaymentTerm();
+                $this->setArrayToMethods(array_filter($requestData['paymentTerm']), $PaymentTerm);
+                $invoiceTemplateData->setPaymentTerm($PaymentTerm);
+            }
+
+            if (isset($requestData['attachments']) && count(array_filter($requestData['attachments'])) > 0) {
+                $attachment = new FileAttachment();
+                $this->setArrayToMethods(array_filter($requestData['attachments']), $attachment);
+                $invoiceTemplateData->setAttachments(array($attachment));
+            }
+
+            // ### Template Settings
+            $displayPreferences = new TemplateSettingsMetadata();
+            if (isset($requestData['TemplateSettingsMetadata']) && count(array_filter($requestData['TemplateSettingsMetadata'])) > 0) {
+                $this->setArrayToMethods(array_filter($requestData['TemplateSettingsMetadata']), $displayPreferences);
+            }
+
+            $settingDate = new TemplateSettings();
+            if (isset($requestData['TemplateSettings']) && count(array_filter($requestData['TemplateSettings'])) > 0) {
+                $this->setArrayToMethods(array_filter($requestData['TemplateSettings']), $settingDate);
+            }
+
+            if (count(array_filter((array)$displayPreferences)) > 0) {
+                $settingDate->setDisplayPreference($displayPreferences);
+            }
+            // ### Template
+            $invoiceTemplate = new Template();
+            $invoiceTemplate->setTemplateId($templateId);
+            if (isset($requestData['Template']) && count(array_filter($requestData['Template'])) > 0) {
+                $this->setArrayToMethods(array_filter($requestData['Template']), $invoiceTemplate);
+            }
+
+            if (count(array_filter((array)$invoiceTemplateData)) > 0) {
+                $invoiceTemplate->setTemplateData($invoiceTemplateData);
+            }
+
+            if (count(array_filter((array)$settingDate)) > 0) {
+                $invoiceTemplate->addSetting($settingDate);
+            }
+
+            $requestArray = clone $invoiceTemplate;
+            $invoiceTemplate->update($this->_api_context);
+            $returnArray['RESULT'] = 'Success';
+            $returnArray['INVOICE_TEMPLATE'] = $invoiceTemplate->toArray();
+            $returnArray['RAWREQUEST'] = $requestArray->toJSON();
+            $returnArray['RAWRESPONSE'] = $invoiceTemplate->toJSON();
+            return $returnArray;
+        } catch (\PayPal\Exception\PayPalConnectionException $ex) {
+            return $this->createErrorResponse($ex);
+        }
+    }
+}
\ No newline at end of file

From c7e28cb557c7ce45148f6e2b0db95f7664fcef24 Mon Sep 17 00:00:00 2001
From: tejas 
Date: Fri, 28 Jun 2019 11:07:22 +0530
Subject: [PATCH 2/5] PPL-170 , added next invoice number api for version two.

---
 .../rest/invoice_v2/GetNextInvoiceNumber.php  | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 samples/rest/invoice_v2/GetNextInvoiceNumber.php

diff --git a/samples/rest/invoice_v2/GetNextInvoiceNumber.php b/samples/rest/invoice_v2/GetNextInvoiceNumber.php
new file mode 100644
index 00000000..6703358b
--- /dev/null
+++ b/samples/rest/invoice_v2/GetNextInvoiceNumber.php
@@ -0,0 +1,22 @@
+ $sandbox,
+    'ClientID' => $rest_client_id,
+    'ClientSecret' => $rest_client_secret,
+    'LogResults' => $log_results, 
+    'LogPath' => $log_path,
+    'LogLevel' => $log_level  
+);
+$PayPal = new \angelleye\PayPal\rest\invoice\InvoiceAPIv2($configArray);
+
+$returnArray = $PayPal->GetNextInvoiceNumber();
+echo "
";
+print_r($returnArray);

From b15628fdcefb2f614106aaa861495a0eb81d1a3b Mon Sep 17 00:00:00 2001
From: tejas 
Date: Fri, 28 Jun 2019 11:10:21 +0530
Subject: [PATCH 3/5] PPL-170 , added api to list and SendInvoice for version 2

---
 .../rest/invoice_v2/GetNextInvoiceNumber.php  |  3 +--
 samples/rest/invoice_v2/ListInvoice.php       | 27 +++++++++++++++++++
 samples/rest/invoice_v2/SendInvoice.php       | 23 ++++++++++++++++
 3 files changed, 51 insertions(+), 2 deletions(-)
 create mode 100644 samples/rest/invoice_v2/ListInvoice.php
 create mode 100644 samples/rest/invoice_v2/SendInvoice.php

diff --git a/samples/rest/invoice_v2/GetNextInvoiceNumber.php b/samples/rest/invoice_v2/GetNextInvoiceNumber.php
index 6703358b..2741ff71 100644
--- a/samples/rest/invoice_v2/GetNextInvoiceNumber.php
+++ b/samples/rest/invoice_v2/GetNextInvoiceNumber.php
@@ -2,7 +2,6 @@
 
 use angelleye\PayPal\rest\invoice\InvoiceAPIv2;
 
-
 // Include required library files.
 require_once('../../../autoload.php');
 require_once('../../../includes/config.php');
@@ -15,7 +14,7 @@
     'LogPath' => $log_path,
     'LogLevel' => $log_level  
 );
-$PayPal = new \angelleye\PayPal\rest\invoice\InvoiceAPIv2($configArray);
+$PayPal = new InvoiceAPIv2($configArray);
 
 $returnArray = $PayPal->GetNextInvoiceNumber();
 echo "
";
diff --git a/samples/rest/invoice_v2/ListInvoice.php b/samples/rest/invoice_v2/ListInvoice.php
new file mode 100644
index 00000000..bae484a2
--- /dev/null
+++ b/samples/rest/invoice_v2/ListInvoice.php
@@ -0,0 +1,27 @@
+ $sandbox,
+    'ClientID' => $rest_client_id,
+    'ClientSecret' => $rest_client_secret,
+    'LogResults' => $log_results, 
+    'LogPath' => $log_path,
+    'LogLevel' => $log_level
+);
+$PayPal = new InvoiceAPIv2($configArray);
+
+$parameters = array(
+    'page'                  => '0',                // A zero-relative index of the list of merchant invoices.
+    'page_size'             => '4',                // The number of invoices to list beginning with the specified page.
+    'total_count_required ' => 'true',             // Indicates whether the total count appears in the response. Default is false.
+);
+
+$returnArray = $PayPal->ListInvoice($parameters);
+echo "
";
+print_r($returnArray);
diff --git a/samples/rest/invoice_v2/SendInvoice.php b/samples/rest/invoice_v2/SendInvoice.php
new file mode 100644
index 00000000..339cde4d
--- /dev/null
+++ b/samples/rest/invoice_v2/SendInvoice.php
@@ -0,0 +1,23 @@
+ $sandbox,
+    'ClientID' => $rest_client_id,
+    'ClientSecret' => $rest_client_secret,
+    'LogResults' => $log_results, 
+    'LogPath' => $log_path,
+    'LogLevel' => $log_level  
+);
+$PayPal = new InvoiceAPIv2($configArray);
+
+$InvoiceID = 'INV2-YZZF-D7VN-P2YM-9ZH2';    // Required. The ID of the invoice to send.
+
+$returnArray = $PayPal->SendInvoice($InvoiceID);
+echo "
";
+print_r($returnArray);

From bfaef20630c572afa12342ccf10c096c6c2595ee Mon Sep 17 00:00:00 2001
From: tejas 
Date: Fri, 28 Jun 2019 11:21:46 +0530
Subject: [PATCH 4/5] PPL-170 , cancel invoice version 2 api added.

---
 samples/rest/invoice_v2/CancelInvoice.php     | 31 +++++++++++++++++++
 src/angelleye/PayPal/InvoicingClass.php       |  5 ++-
 .../PayPal/rest/invoice/InvoiceAPIv2.php      |  5 ++-
 3 files changed, 35 insertions(+), 6 deletions(-)
 create mode 100644 samples/rest/invoice_v2/CancelInvoice.php

diff --git a/samples/rest/invoice_v2/CancelInvoice.php b/samples/rest/invoice_v2/CancelInvoice.php
new file mode 100644
index 00000000..92e7cb61
--- /dev/null
+++ b/samples/rest/invoice_v2/CancelInvoice.php
@@ -0,0 +1,31 @@
+ $sandbox,
+    'ClientID' => $rest_client_id,
+    'ClientSecret' => $rest_client_secret,
+    'LogResults' => $log_results, 
+    'LogPath' => $log_path,
+    'LogLevel' => $log_level  
+);
+$PayPal = new InvoiceAPIv2($configArray);
+
+$cancelNotification = array(
+    'subject' => 'Past due',                      // Subject of the notification.
+    'note'    => 'Canceling invoice',             // Note to the payer.
+    'send_to_invoicer' => true,                   // Indicates whether to send a copy of the notification to the merchant.
+    'send_to_recipient' => true,                  // Indicates whether to send a copy of the notification to the payer.
+    'additional_recipients' => array(),             // Applicable for invoices created with Cc emails. If this field is not in the body, all the cc email addresses added as part of the invoice shall be notified else this field can be used to limit the list of email addresses. Note: additional email addresses are not supported.    
+);
+
+$InvoiceID = 'INV2-YZZF-D7VN-P2YM-9ZH2';          // Required. Specify the ID of the invoice to cancel.
+
+$returnArray = $PayPal->CancelInvoice($cancelNotification,$InvoiceID);
+echo "
";
+print_r($returnArray);
diff --git a/src/angelleye/PayPal/InvoicingClass.php b/src/angelleye/PayPal/InvoicingClass.php
index 3821652c..6c32b0db 100644
--- a/src/angelleye/PayPal/InvoicingClass.php
+++ b/src/angelleye/PayPal/InvoicingClass.php
@@ -939,9 +939,8 @@ public function remind($notification, $apiContext = null, $restCall = null) {
      * @return bool
      */
     public function cancel($cancelNotification, $apiContext = null, $restCall = null) {
-        ArgumentValidator::validate($this->getId(), "Id");
-        ArgumentValidator::validate($cancelNotification, 'cancelNotification');
-        $payLoad = $cancelNotification->toJSON();
+
+        $payLoad = (!empty($cancelNotification)) ? json_encode($cancelNotification) : '';        
         self::executeCall(
                 "/v2/invoicing/invoices/{$this->getId()}/cancel", "POST", $payLoad, null, $apiContext, $restCall
         );
diff --git a/src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php b/src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php
index a968a0ab..966bed5e 100644
--- a/src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php
+++ b/src/angelleye/PayPal/rest/invoice/InvoiceAPIv2.php
@@ -365,9 +365,8 @@ public function GetThirdPartyInvoice($invoiceId, $refreshToken)
     public function CancelInvoice($cancelNotification, $InvoiceID, $third_party = false, $refesh_token = '')
     {
         try {
-            $notify = new CancelNotification();
-            $this->setArrayToMethods(array_filter($cancelNotification), $notify);
 
+            $notify = array_filter($cancelNotification);
             $invoice = new InvoicingClass();
             $invoice->setId($InvoiceID);
             if ($third_party === true  && !empty($refesh_token)) {
@@ -378,7 +377,7 @@ public function CancelInvoice($cancelNotification, $InvoiceID, $third_party = fa
 
             $returnArray['RESULT'] = 'Success';
             $returnArray['CANCEL_STATUS'] = $cancelStatus;
-            $returnArray['RAWREQUEST'] = $requestArray;
+            $returnArray['RAWREQUEST'] = $requestArray->toJSON();
             $returnArray['RAWRESPONSE'] = $cancelStatus;
             return $returnArray;
         } catch (\PayPal\Exception\PayPalConnectionException $ex) {

From 809a028fc6a82aecd10ce0d27522aeda71e4315d Mon Sep 17 00:00:00 2001
From: tejas 
Date: Fri, 28 Jun 2019 11:29:42 +0530
Subject: [PATCH 5/5] PPL-170 ,  Delete Invoice version 2 api added.

---
 samples/rest/invoice_v2/DeleteInvoice.php | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 samples/rest/invoice_v2/DeleteInvoice.php

diff --git a/samples/rest/invoice_v2/DeleteInvoice.php b/samples/rest/invoice_v2/DeleteInvoice.php
new file mode 100644
index 00000000..00f2c07f
--- /dev/null
+++ b/samples/rest/invoice_v2/DeleteInvoice.php
@@ -0,0 +1,23 @@
+ $sandbox,
+    'ClientID' => $rest_client_id,
+    'ClientSecret' => $rest_client_secret,
+    'LogResults' => $log_results, 
+    'LogPath' => $log_path,
+    'LogLevel' => $log_level  
+);
+$PayPal = new InvoiceAPIv2($configArray);
+
+$InvoiceID = 'INV2-YZZF-D7VN-P2YM-9ZH2';    // Required.  The ID of the invoice for which to show details.
+
+$returnArray = $PayPal->DeleteInvoice($InvoiceID);
+echo "
";
+print_r($returnArray);
\ No newline at end of file