forked from go-packages/paypal
* feature/Invoice: init, added Invoice related structs, implemented methods:GenerateInvoiceNumber,GetInvoiceDetails(by ID) * feature/Invoice: added implemented endpoints to README along with Usage Co-authored-by: Akshay Prabhakant <akshayprabhakant@Akshays-MacBook-Pro.local>
This commit is contained in:
parent
1bb626d559
commit
4c16ffad0a
26
README.md
26
README.md
|
@ -101,6 +101,11 @@
|
|||
* POST /v1/billing/subscriptions/:id/capture
|
||||
* POST /v1/billing/subscriptions/:id/suspend
|
||||
* GET /v1/billing/subscriptions/:id/transactions
|
||||
|
||||
### Invoicing
|
||||
|
||||
* POST /v2/invoicing/generate-next-invoice-number
|
||||
* GET /v2/invoicing/invoices/:id
|
||||
|
||||
## Missing endpoints
|
||||
|
||||
|
@ -371,6 +376,27 @@ c.DeleteWebhook("WebhookID")
|
|||
c.ListWebhooks(paypal.AncorTypeApplication)
|
||||
```
|
||||
|
||||
### Generate Next Invoice Number
|
||||
```go
|
||||
// GenerateInvoiceNumber: generates the next invoice number that is available to the merchant.
|
||||
c.GenerateInvoiceNumber(ctx) // might return something like "0001" or "0010".
|
||||
```
|
||||
|
||||
### Get Invoice Details by ID
|
||||
```go
|
||||
// the second argument is an ID, it should be valid
|
||||
invoice, err := c.GetInvoiceDetails(ctx, "INV2-XFXV-YW42-ZANU-4F33")
|
||||
```
|
||||
* for now, we are yet to implement the ShowAllInvoices endpoint, so use the following cURL request for the same(this gives you the list of invoice-IDs for this customer)
|
||||
```bash
|
||||
curl -v -X GET https://api-m.sandbox.paypal.com/v2/invoicing/invoices?total_required=true \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer <Token>"
|
||||
```
|
||||
|
||||
* refer to the beginning of this Usage section for obtaining a Token.
|
||||
|
||||
|
||||
## How to Contribute
|
||||
|
||||
* Fork a repository
|
||||
|
|
38
invoicing.go
Normal file
38
invoicing.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package paypal
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// GenerateInvoiceNumber: generates the next invoice number that is available to the merchant.
|
||||
// Endpoint: POST /v2/invoicing/generate-next-invoice-number
|
||||
func (c *Client) GenerateInvoiceNumber(ctx context.Context) (*InvoiceNumber, error) {
|
||||
|
||||
req, err := c.NewRequest(ctx, "POST", fmt.Sprintf("%s%s", c.APIBase, "/v2/invoicing/generate-next-invoice-number"), nil)
|
||||
nextInvoiceNumber := &InvoiceNumber{}
|
||||
if err != nil {
|
||||
return nextInvoiceNumber, err
|
||||
}
|
||||
|
||||
if err = c.SendWithAuth(req, nextInvoiceNumber); err != nil {
|
||||
return nextInvoiceNumber, err
|
||||
}
|
||||
|
||||
return nextInvoiceNumber, nil
|
||||
}
|
||||
|
||||
// GetInvoiceDetails: show invoice details for a particular invoice by ID.
|
||||
// Endpoint: GET /v2/invoicing/invoices/{invoice_id}
|
||||
func (c *Client) GetInvoiceDetails(ctx context.Context, invoiceID string) (*Invoice, error) {
|
||||
req, err := c.NewRequest(ctx, "GET", fmt.Sprintf("%s%s%s", c.APIBase, "/v2/invoicing/invoices/", invoiceID), nil)
|
||||
invoice := &Invoice{}
|
||||
if err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
if err = c.SendWithAuth(req, invoice); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
return invoice, nil
|
||||
}
|
406
invoicing_test.go
Normal file
406
invoicing_test.go
Normal file
|
@ -0,0 +1,406 @@
|
|||
package paypal_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/plutov/paypal/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// All test values are defined here
|
||||
var devTestClientID = "AXy9orp-CDaHhBZ9C78QHW2BKZpACgroqo85_NIOa9mIfJ9QnSVKzY-X_rivR_fTUUr6aLjcJsj6sDur"
|
||||
var devTestSecret = "EBoIiUSkCKeSk49hHSgTem1qnjzzJgRQHDEHvGpzlLEf_nIoJd91xu8rPOBDCdR_UYNKVxJE-UgS2iCw"
|
||||
var devAPIBaseSandBox = "https://api.sandbox.paypal.com"
|
||||
|
||||
func TestGenerateInvoiceNumber(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
c, _ := paypal.NewClient(devTestClientID, devTestSecret, devAPIBaseSandBox)
|
||||
_, err := c.GetAccessToken(ctx)
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
_, err = c.GenerateInvoiceNumber(ctx)
|
||||
assert.Equal(t, nil, err)
|
||||
}
|
||||
func assertTwoInvoices(t *testing.T, invoice paypal.Invoice, testInvoice paypal.Invoice) {
|
||||
|
||||
// additional_recipients
|
||||
assert.Equal(t, len(invoice.AdditionalRecipients), len(testInvoice.AdditionalRecipients))
|
||||
// additional_recipients --> email_address !! EQUALITY OF SPLICE OF STRUCT REMAINING !!
|
||||
|
||||
// amount
|
||||
assert.Equal(t, invoice.AmountSummary.Currency, testInvoice.AmountSummary.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Value, testInvoice.AmountSummary.Value)
|
||||
// amount-->breakdown-->custom-->amount
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Custom.Amount.Currency, testInvoice.AmountSummary.Breakdown.Custom.Amount.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Custom.Amount.Value, testInvoice.AmountSummary.Breakdown.Custom.Amount.Value)
|
||||
// amount-->breakdown-->custom-->label
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Custom.Label, testInvoice.AmountSummary.Breakdown.Custom.Label)
|
||||
// amount-->breakdown-->discount-->amount
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Discount.InvoiceDiscount.DiscountAmount.Currency, testInvoice.AmountSummary.Breakdown.Discount.InvoiceDiscount.DiscountAmount.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Discount.InvoiceDiscount.DiscountAmount.Value, testInvoice.AmountSummary.Breakdown.Discount.InvoiceDiscount.DiscountAmount.Value)
|
||||
// amount-->breakdown-->discount-->percent
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Discount.InvoiceDiscount.Percent, testInvoice.AmountSummary.Breakdown.Discount.InvoiceDiscount.Percent)
|
||||
// amount-->breakdown-->discount-->item_discount
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Discount.ItemDiscount.Currency, testInvoice.AmountSummary.Breakdown.Discount.ItemDiscount.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Discount.ItemDiscount.Value, testInvoice.AmountSummary.Breakdown.Discount.ItemDiscount.Value)
|
||||
// amount-->breakdown-->item_total
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.ItemTotal.Currency, testInvoice.AmountSummary.Breakdown.ItemTotal.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.ItemTotal.Value, testInvoice.AmountSummary.Breakdown.ItemTotal.Value)
|
||||
// amount-->breakdown-->shipping-->amount
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Shipping.Amount.Currency, testInvoice.AmountSummary.Breakdown.Shipping.Amount.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Shipping.Amount.Value, testInvoice.AmountSummary.Breakdown.Shipping.Amount.Value)
|
||||
// amount-->breakdown-->shipping-->tax
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Shipping.Tax.Amount.Currency, testInvoice.AmountSummary.Breakdown.Shipping.Tax.Amount.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Shipping.Tax.Amount.Value, testInvoice.AmountSummary.Breakdown.Shipping.Tax.Amount.Value)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Shipping.Tax.ID, testInvoice.AmountSummary.Breakdown.Shipping.Tax.ID)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Shipping.Tax.Name, testInvoice.AmountSummary.Breakdown.Shipping.Tax.Name)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.Shipping.Tax.Percent, testInvoice.AmountSummary.Breakdown.Shipping.Tax.Percent)
|
||||
// amount-->breakdown-->tax_total
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.TaxTotal.Currency, testInvoice.AmountSummary.Breakdown.TaxTotal.Currency)
|
||||
assert.Equal(t, invoice.AmountSummary.Breakdown.TaxTotal.Value, testInvoice.AmountSummary.Breakdown.TaxTotal.Value)
|
||||
|
||||
// configuration
|
||||
assert.Equal(t, invoice.Configuration.AllowTip, testInvoice.Configuration.AllowTip)
|
||||
assert.Equal(t, invoice.Configuration.TaxCalculatedAfterDiscount, testInvoice.Configuration.TaxCalculatedAfterDiscount)
|
||||
assert.Equal(t, invoice.Configuration.TaxInclusive, testInvoice.Configuration.TaxInclusive)
|
||||
assert.Equal(t, invoice.Configuration.TemplateId, testInvoice.Configuration.TemplateId)
|
||||
// configuration --> partial_payment
|
||||
assert.Equal(t, invoice.Configuration.PartialPayment.AllowPartialPayment, testInvoice.Configuration.PartialPayment.AllowPartialPayment)
|
||||
assert.Equal(t, invoice.Configuration.PartialPayment.MinimumAmountDue.Currency, testInvoice.Configuration.PartialPayment.MinimumAmountDue.Currency)
|
||||
assert.Equal(t, invoice.Configuration.PartialPayment.MinimumAmountDue.Value, testInvoice.Configuration.PartialPayment.MinimumAmountDue.Value)
|
||||
|
||||
// detail
|
||||
assert.Equal(t, invoice.Detail.CurrencyCode, testInvoice.Detail.CurrencyCode)
|
||||
assert.Equal(t, invoice.Detail.InvoiceDate, testInvoice.Detail.InvoiceDate)
|
||||
assert.Equal(t, invoice.Detail.InvoiceNumber, testInvoice.Detail.InvoiceNumber)
|
||||
assert.Equal(t, invoice.Detail.Memo, testInvoice.Detail.Memo)
|
||||
assert.Equal(t, invoice.Detail.Note, testInvoice.Detail.Note)
|
||||
assert.Equal(t, invoice.Detail.Reference, testInvoice.Detail.Reference)
|
||||
assert.Equal(t, invoice.Detail.TermsAndConditions, testInvoice.Detail.TermsAndConditions)
|
||||
// detail --> attachments !! EQUALITY OF SPLICE OF STRUCT REMAINING !!
|
||||
assert.Equal(t, len(invoice.Detail.Attachments), len(testInvoice.Detail.Attachments))
|
||||
// detail --> metadata
|
||||
assert.Equal(t, invoice.Detail.Metadata.CancelTime, testInvoice.Detail.Metadata.CancelTime)
|
||||
assert.Equal(t, invoice.Detail.Metadata.CancellledTimeBy, testInvoice.Detail.Metadata.CancellledTimeBy)
|
||||
assert.Equal(t, invoice.Detail.Metadata.CreateTime, testInvoice.Detail.Metadata.CreateTime)
|
||||
assert.Equal(t, invoice.Detail.Metadata.CreatedBy, testInvoice.Detail.Metadata.CreatedBy)
|
||||
assert.Equal(t, invoice.Detail.Metadata.CreatedByFlow, testInvoice.Detail.Metadata.CreatedByFlow)
|
||||
assert.Equal(t, invoice.Detail.Metadata.FirstSentTime, testInvoice.Detail.Metadata.FirstSentTime)
|
||||
assert.Equal(t, invoice.Detail.Metadata.InvoicerViewUrl, testInvoice.Detail.Metadata.InvoicerViewUrl)
|
||||
assert.Equal(t, invoice.Detail.Metadata.LastSentBy, testInvoice.Detail.Metadata.LastSentBy)
|
||||
assert.Equal(t, invoice.Detail.Metadata.LastSentTime, testInvoice.Detail.Metadata.LastSentTime)
|
||||
assert.Equal(t, invoice.Detail.Metadata.LastUpdateTime, testInvoice.Detail.Metadata.LastUpdateTime)
|
||||
assert.Equal(t, invoice.Detail.Metadata.LastUpdatedBy, testInvoice.Detail.Metadata.LastUpdatedBy)
|
||||
assert.Equal(t, invoice.Detail.Metadata.RecipientViewUrl, testInvoice.Detail.Metadata.RecipientViewUrl)
|
||||
// detail --> payment_term
|
||||
assert.Equal(t, invoice.Detail.PaymentTerm.DueDate, testInvoice.Detail.PaymentTerm.DueDate)
|
||||
assert.Equal(t, invoice.Detail.PaymentTerm.TermType, testInvoice.Detail.PaymentTerm.TermType)
|
||||
|
||||
// due_amount
|
||||
assert.Equal(t, invoice.DueAmount.Currency, testInvoice.DueAmount.Currency)
|
||||
assert.Equal(t, invoice.DueAmount.Value, testInvoice.DueAmount.Value)
|
||||
|
||||
// gratuity
|
||||
assert.Equal(t, invoice.Gratuity.Currency, testInvoice.Gratuity.Currency)
|
||||
assert.Equal(t, invoice.Gratuity.Value, testInvoice.Gratuity.Value)
|
||||
|
||||
// id
|
||||
assert.Equal(t, invoice.ID, testInvoice.ID)
|
||||
|
||||
// invoicer
|
||||
assert.Equal(t, invoice.Invoicer.AdditionalNotes, testInvoice.Invoicer.AdditionalNotes)
|
||||
assert.Equal(t, invoice.Invoicer.EmailAddress, testInvoice.Invoicer.EmailAddress)
|
||||
assert.Equal(t, invoice.Invoicer.LogoUrl, testInvoice.Invoicer.LogoUrl)
|
||||
assert.Equal(t, invoice.Invoicer.TaxId, testInvoice.Invoicer.TaxId)
|
||||
assert.Equal(t, invoice.Invoicer.Website, testInvoice.Invoicer.Website)
|
||||
// !!! SPLICE EQUALITY STILL REMAINING !!!!!
|
||||
// invoicer --> phones
|
||||
assert.Equal(t, len(invoice.Invoicer.Phones), len(testInvoice.Invoicer.Phones))
|
||||
|
||||
// items
|
||||
// !!! SPLICE EQUALITY STILL REMAINING !!!!!
|
||||
assert.Equal(t, len(invoice.Items), len(testInvoice.Items))
|
||||
|
||||
// links
|
||||
// !!! SPLICE EQUALITY STILL REMAINING !!!!!
|
||||
assert.Equal(t, len(invoice.Links), len(testInvoice.Links))
|
||||
|
||||
// parent_id
|
||||
assert.Equal(t, invoice.ParentID, testInvoice.ParentID)
|
||||
|
||||
// payments
|
||||
assert.Equal(t, invoice.Payments.PaidAmount.Currency, testInvoice.Payments.PaidAmount.Currency)
|
||||
assert.Equal(t, invoice.Payments.PaidAmount.Value, testInvoice.Payments.PaidAmount.Value)
|
||||
// payments --> transactions
|
||||
assert.Equal(t, len(invoice.Payments.Transactions), len(testInvoice.Payments.Transactions))
|
||||
|
||||
// primary_recipients
|
||||
// !!! SPLICE EQUALITY STILL REMAINING !!!!!
|
||||
assert.Equal(t, len(invoice.PrimaryRecipients), len(testInvoice.PrimaryRecipients))
|
||||
|
||||
// refunds
|
||||
assert.Equal(t, invoice.Refunds.RefundAmount.Currency, testInvoice.Refunds.RefundAmount.Currency)
|
||||
assert.Equal(t, invoice.Refunds.RefundAmount.Value, testInvoice.Refunds.RefundAmount.Value)
|
||||
assert.Equal(t, len(invoice.Refunds.RefundDetails), len(testInvoice.Refunds.RefundDetails))
|
||||
|
||||
// status
|
||||
assert.Equal(t, invoice.Status, testInvoice.Status)
|
||||
|
||||
}
|
||||
|
||||
func TestGetInvoice(t *testing.T) {
|
||||
testInvoiceJSONData := []byte(`
|
||||
{
|
||||
"amount": {
|
||||
"breakdown": {
|
||||
"custom": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "10.00"
|
||||
},
|
||||
"label": "Packing Charges"
|
||||
},
|
||||
"discount": {
|
||||
"invoice_discount": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "-2.63"
|
||||
},
|
||||
"percent": "5"
|
||||
},
|
||||
"item_discount": {
|
||||
"currency_code": "USD",
|
||||
"value": "-7.50"
|
||||
}
|
||||
},
|
||||
"item_total": {
|
||||
"currency_code": "USD",
|
||||
"value": "60.00"
|
||||
},
|
||||
"shipping": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "10.00"
|
||||
},
|
||||
"tax": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "0.73"
|
||||
},
|
||||
"id": "TAX-9AU06895VD287170A",
|
||||
"name": "Sales Tax",
|
||||
"percent": "7.25"
|
||||
}
|
||||
},
|
||||
"tax_total": {
|
||||
"currency_code": "USD",
|
||||
"value": "4.34"
|
||||
}
|
||||
},
|
||||
"currency_code": "USD",
|
||||
"value": "74.21"
|
||||
},
|
||||
"configuration": {
|
||||
"allow_tip": true,
|
||||
"partial_payment": {
|
||||
"allow_partial_payment": true,
|
||||
"minimum_amount_due": {
|
||||
"currency_code": "USD",
|
||||
"value": "20.00"
|
||||
}
|
||||
},
|
||||
"tax_calculated_after_discount": true,
|
||||
"tax_inclusive": false,
|
||||
"template_id": "TEMP-4NW98229SC0703920"
|
||||
},
|
||||
"detail": {
|
||||
"additional_data": "2-4",
|
||||
"archived": false,
|
||||
"category_code": "SHIPPABLE",
|
||||
"currency_code": "USD",
|
||||
"group_draft": false,
|
||||
"invoice_date": "2018-11-12",
|
||||
"invoice_number": "0001",
|
||||
"memo": "This is a long contract",
|
||||
"metadata": {
|
||||
"caller_type": "API_V2_INVOICE",
|
||||
"create_time": "2022-10-25T16:54:50Z",
|
||||
"created_by_flow": "REGULAR_SINGLE",
|
||||
"invoicer_view_url": "https://www.sandbox.paypal.com/invoice/details/INV2-XFXV-YW42-ZANU-4F33",
|
||||
"last_update_time": "2022-10-25T16:54:50Z",
|
||||
"recipient_view_url": "https://www.sandbox.paypal.com/invoice/p/#XFXVYW42ZANU4F33"
|
||||
},
|
||||
"note": "Thank you for your business.",
|
||||
"payment_term": {
|
||||
"due_date": "2018-11-22",
|
||||
"term_type": "NET_10"
|
||||
},
|
||||
"reference": "deal-ref",
|
||||
"viewed_by_recipient": false
|
||||
},
|
||||
"due_amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "74.21"
|
||||
},
|
||||
"id": "INV2-XFXV-YW42-ZANU-4F33",
|
||||
"invoicer": {
|
||||
"additional_notes": "2-4",
|
||||
"address": {
|
||||
"address_line_1": "1234 First Street",
|
||||
"address_line_2": "337673 Hillside Court",
|
||||
"admin_area_1": "CA",
|
||||
"admin_area_2": "Anytown",
|
||||
"country_code": "US",
|
||||
"postal_code": "98765"
|
||||
},
|
||||
"email_address": "merchant@example.com",
|
||||
"logo_url": "https://example.com/logo.PNG",
|
||||
"name": {
|
||||
"full_name": "David Larusso",
|
||||
"given_name": "David",
|
||||
"surname": "Larusso"
|
||||
},
|
||||
"phones": [
|
||||
{
|
||||
"country_code": "001",
|
||||
"national_number": "4085551234",
|
||||
"phone_type": "MOBILE"
|
||||
}
|
||||
],
|
||||
"tax_id": "ABcNkWSfb5ICTt73nD3QON1fnnpgNKBy- Jb5SeuGj185MNNw6g",
|
||||
"website": "www.test.com"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"description": "Elastic mat to practice yoga.",
|
||||
"discount": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "-2.50"
|
||||
},
|
||||
"percent": "5"
|
||||
},
|
||||
"id": "ITEM-5335764681676603X",
|
||||
"name": "Yoga Mat",
|
||||
"quantity": "1",
|
||||
"tax": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "3.27"
|
||||
},
|
||||
"id": "TAX-5XV24702TP4910056",
|
||||
"name": "Sales Tax",
|
||||
"percent": "7.25"
|
||||
},
|
||||
"unit_amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "50.00"
|
||||
},
|
||||
"unit_of_measure": "QUANTITY"
|
||||
},
|
||||
{
|
||||
"discount": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "-5.00"
|
||||
}
|
||||
},
|
||||
"id": "ITEM-1B467958Y9218273X",
|
||||
"name": "Yoga t-shirt",
|
||||
"quantity": "1",
|
||||
"tax": {
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "0.34"
|
||||
},
|
||||
"id": "TAX-5XV24702TP4910056",
|
||||
"name": "Sales Tax",
|
||||
"percent": "7.25"
|
||||
},
|
||||
"unit_amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "10.00"
|
||||
},
|
||||
"unit_of_measure": "QUANTITY"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-XFXV-YW42-ZANU-4F33",
|
||||
"method": "GET",
|
||||
"rel": "self"
|
||||
},
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-XFXV-YW42-ZANU-4F33/send",
|
||||
"method": "POST",
|
||||
"rel": "send"
|
||||
},
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-XFXV-YW42-ZANU-4F33",
|
||||
"method": "PUT",
|
||||
"rel": "replace"
|
||||
},
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-XFXV-YW42-ZANU-4F33",
|
||||
"method": "DELETE",
|
||||
"rel": "delete"
|
||||
},
|
||||
{
|
||||
"href": "https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-XFXV-YW42-ZANU-4F33/payments",
|
||||
"method": "POST",
|
||||
"rel": "record-payment"
|
||||
}
|
||||
],
|
||||
"primary_recipients": [
|
||||
{
|
||||
"billing_info": {
|
||||
"address": {
|
||||
"address_line_1": "1234 Main Street",
|
||||
"admin_area_1": "CA",
|
||||
"admin_area_2": "Anytown",
|
||||
"country_code": "US",
|
||||
"postal_code": "98765"
|
||||
},
|
||||
"email_address": "bill-me@example.com",
|
||||
"name": {
|
||||
"full_name": "Stephanie Meyers",
|
||||
"given_name": "Stephanie",
|
||||
"surname": "Meyers"
|
||||
}
|
||||
},
|
||||
"shipping_info": {
|
||||
"address": {
|
||||
"address_line_1": "1234 Main Street",
|
||||
"admin_area_1": "CA",
|
||||
"admin_area_2": "Anytown",
|
||||
"country_code": "US",
|
||||
"postal_code": "98765"
|
||||
},
|
||||
"name": {
|
||||
"full_name": "Stephanie Meyers",
|
||||
"given_name": "Stephanie",
|
||||
"surname": "Meyers"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"status": "DRAFT",
|
||||
"unilateral": false
|
||||
}
|
||||
`)
|
||||
var testInvoice paypal.Invoice
|
||||
err := json.Unmarshal(testInvoiceJSONData, &testInvoice)
|
||||
assert.Equal(t, nil, err) // if passed, means unmarshalling was successful
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
c, _ := paypal.NewClient(devTestClientID, devTestSecret, devAPIBaseSandBox)
|
||||
_, _ = c.GetAccessToken(ctx)
|
||||
|
||||
invoice, err := c.GetInvoiceDetails(ctx, "INV2-XFXV-YW42-ZANU-4F33")
|
||||
assert.Equal(t, nil, err) // if passed, means that request was successful
|
||||
assertTwoInvoices(t, *invoice, testInvoice)
|
||||
}
|
258
types.go
258
types.go
|
@ -204,6 +204,264 @@ type (
|
|||
CancelURL string `json:"cancel_url,omitempty"`
|
||||
}
|
||||
|
||||
// Invoicing relates structures
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#invoices_generate-next-invoice-number
|
||||
InvoiceNumber struct {
|
||||
InvoiceNumberValue string `json:"invoice_number"`
|
||||
}
|
||||
|
||||
// used in InvoiceAmountWithBreakdown
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-custom_amount
|
||||
CustomAmount struct {
|
||||
Label string `json:"label"`
|
||||
Amount Money `json:"amount,omitempty"`
|
||||
}
|
||||
// Used in AggregatedDiscount
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-discount
|
||||
InvoicingDiscount struct {
|
||||
DiscountAmount Money `json:"amount,omitempty"`
|
||||
Percent string `json:"percent,omitempty"`
|
||||
}
|
||||
// Used in InvoiceAmountWithBreakdown
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-aggregated_discount
|
||||
AggregatedDiscount struct {
|
||||
InvoiceDiscount InvoicingDiscount `json:"invoice_discount,omitempty"`
|
||||
ItemDiscount *Money `json:"item_discount,omitempty"`
|
||||
}
|
||||
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-tax
|
||||
InvoiceTax struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Percent string `json:"percent,omitempty"`
|
||||
ID string `json:"id,omitempty"` // not mentioned here, but is still returned in response payload, when invoice is requested by ID.
|
||||
Amount Money `json:"amount,omitempty"`
|
||||
}
|
||||
// Used in InvoiceAmountWithBreakdown struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-shipping_cost
|
||||
InvoiceShippingCost struct {
|
||||
Amount Money `json:"amount,omitempty"`
|
||||
Tax InvoiceTax `json:"tax,omitempty"`
|
||||
}
|
||||
|
||||
// Used in AmountSummaryDetail
|
||||
// Doc: https://developer.paypal.com/docs/api/payments/v2/#definition-nrp-nrr_attributes
|
||||
InvoiceAmountWithBreakdown struct {
|
||||
Custom CustomAmount `json:"custom,omitempty"` // The custom amount to apply to an invoice.
|
||||
Discount AggregatedDiscount `json:"discount,omitempty"`
|
||||
ItemTotal Money `json:"item_total,omitempty"` // The subtotal for all items.
|
||||
Shipping InvoiceShippingCost `json:"shipping,omitempty"` // The shipping fee for all items. Includes tax on shipping.
|
||||
TaxTotal Money `json:"tax_total,omitempty"`
|
||||
}
|
||||
|
||||
// Invoice AmountSummary
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-amount_summary_detail
|
||||
AmountSummaryDetail struct {
|
||||
Breakdown InvoiceAmountWithBreakdown `json:"breakdown,omitempty"`
|
||||
Currency string `json:"currency_code,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
}
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-partial_payment
|
||||
InvoicePartialPayment struct {
|
||||
AllowPartialPayment bool `json:"allow_partial_payment,omitempty"`
|
||||
MinimumAmountDue Money `json:"minimum_amount_due,omitempty"` // Valid only when allow_partial_payment is true.
|
||||
}
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-configuration
|
||||
InvoiceConfiguration struct {
|
||||
AllowTip bool `json:"allow_tip,omitempty"`
|
||||
PartialPayment InvoicePartialPayment `json:"partial_payment,omitempty"`
|
||||
TaxCalculatedAfterDiscount bool `json:"tax_calculated_after_discount,omitempty"`
|
||||
TaxInclusive bool `json:"tax_inclusive,omitempty"`
|
||||
TemplateId string `json:"template_id,omitempty"`
|
||||
}
|
||||
// used in InvoiceDetail structure
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-file_reference
|
||||
InvoiceFileReference struct {
|
||||
ContentType string `json:"content_type,omitempty"`
|
||||
CreateTime string `json:"create_time,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
URL string `json:"reference_url,omitempty"`
|
||||
Size string `json:"size,omitempty"`
|
||||
}
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-metadata
|
||||
InvoiceAuditMetadata struct {
|
||||
CreateTime string `json:"create_time,omitempty"`
|
||||
CreatedBy string `json:"created_by,omitempty"`
|
||||
LastUpdateTime string `json:"last_update_time,omitempty"`
|
||||
LastUpdatedBy string `json:"last_updated_by,omitempty"`
|
||||
CancelTime string `json:"cancel_time,omitempty"`
|
||||
CancellledTimeBy string `json:"cancelled_by,omitempty"`
|
||||
CreatedByFlow string `json:"created_by_flow,omitempty"`
|
||||
FirstSentTime string `json:"first_sent_time,omitempty"`
|
||||
InvoicerViewUrl string `json:"invoicer_view_url,omitempty"`
|
||||
LastSentBy string `json:"last_sent_by,omitempty"`
|
||||
LastSentTime string `json:"last_sent_time,omitempty"`
|
||||
RecipientViewUrl string `json:"recipient_view_url,omitempty"`
|
||||
}
|
||||
// used in InvoiceDetail struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-invoice_payment_term
|
||||
InvoicePaymentTerm struct {
|
||||
TermType string `json:"term_type,omitempty"`
|
||||
DueDate string `json:"due_date,omitempty"`
|
||||
}
|
||||
|
||||
// used in Invoice struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-invoice_detail
|
||||
InvoiceDetail struct {
|
||||
CurrencyCode string `json:"currency_code"` // required, hence omitempty not used
|
||||
Attachments []InvoiceFileReference `json:"attachments,omitempty"`
|
||||
Memo string `json:"memo,omitempty"`
|
||||
Note string `json:"note,omitempty"`
|
||||
Reference string `json:"reference,omitempty"`
|
||||
TermsAndConditions string `json:"terms_and_conditions,omitempty"`
|
||||
InvoiceDate string `json:"invoice_date,omitempty"`
|
||||
InvoiceNumber string `json:"invoice_number,omitempty"`
|
||||
Metadata InvoiceAuditMetadata `json:"metadata,omitempty"` // The audit metadata.
|
||||
PaymentTerm InvoicePaymentTerm `json:"payment_term,omitempty"` // payment due date for the invoice. Value is either but not both term_type or due_date.
|
||||
}
|
||||
|
||||
// used in InvoicerInfo struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-phone_detail
|
||||
InvoicerPhoneDetail struct {
|
||||
CountryCode string `json:"country_code"`
|
||||
NationalNumber string `json:"national_number"`
|
||||
ExtensionNumber string `json:"extension_number,omitempty"`
|
||||
PhoneType string `json:"phone_type,omitempty"`
|
||||
}
|
||||
|
||||
// used in Invoice struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-invoicer_info
|
||||
InvoicerInfo struct {
|
||||
AdditionalNotes string `json:"additional_notes,omitempty"`
|
||||
EmailAddress string `json:"email_address,omitempty"`
|
||||
LogoUrl string `json:"logo_url,omitempty"`
|
||||
Phones []InvoicerPhoneDetail `json:"phones,omitempty"`
|
||||
TaxId string `json:"tax_id,omitempty"`
|
||||
Website string `json:"website,omitempty"`
|
||||
}
|
||||
// Used in Invoice struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-item
|
||||
InvoiceItem struct {
|
||||
Name string `json:"name"`
|
||||
Quantity string `json:"quantity"`
|
||||
UnitAmount Money `json:"unit_amount"`
|
||||
Description string `json:"description,omitempty"`
|
||||
InvoiceDiscount InvoicingDiscount `json:"discount,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
ItemDate string `json:"item_date,omitempty"`
|
||||
Tax InvoiceTax `json:"tax,omitempty"`
|
||||
UnitOfMeasure string `json:"unit_of_measure,omitempty"`
|
||||
}
|
||||
|
||||
// used in InvoiceAddressPortable
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-address_details
|
||||
InvoiceAddressDetails struct {
|
||||
BuildingName string `json:"building_name,omitempty"`
|
||||
DeliveryService string `json:"delivery_service,omitempty"`
|
||||
StreetName string `json:"street_name,omitempty"`
|
||||
StreetNumber string `json:"street_number,omitempty"`
|
||||
StreetType string `json:"street_type,omitempty"`
|
||||
SubBuilding string `json:"sub_building,omitempty"`
|
||||
}
|
||||
|
||||
// used in InvoiceContactInfo
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-address_portable
|
||||
InvoiceAddressPortable struct {
|
||||
CountryCode string `json:"country_code"`
|
||||
AddressDetails InvoiceAddressDetails `json:"address_details,omitempty"`
|
||||
AddressLine1 string `json:"address_line_1,omitempty"`
|
||||
AddressLine2 string `json:"address_line_2,omitempty"`
|
||||
AddressLine3 string `json:"address_line_3,omitempty"`
|
||||
AdminArea1 string `json:"admin_area_1,omitempty"`
|
||||
AdminArea2 string `json:"admin_area_2,omitempty"`
|
||||
AdminArea3 string `json:"admin_area_3,omitempty"`
|
||||
AdminArea4 string `json:"admin_area_4,omitempty"`
|
||||
PostalCode string `json:"postal_code,omitempty"`
|
||||
}
|
||||
|
||||
// used in InvoicePaymentDetails
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-contact_information
|
||||
InvoiceContactInfo struct {
|
||||
BusinessName string `json:"business_name,omitempty"`
|
||||
RecipientAddress InvoiceAddressPortable `json:"address,omitempty"` // address of the recipient.
|
||||
RecipientName Name `json:"name,omitempty"` // The first and Last name of the recipient.
|
||||
}
|
||||
//used in InvoicePayments struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-payment_detail
|
||||
InvoicePaymentDetails struct {
|
||||
Method string `json:"method"`
|
||||
Amount Money `json:"amount,omitempty"`
|
||||
Note string `json:"note,omitempty"`
|
||||
PaymentDate string `json:"payment_date,omitempty"`
|
||||
PaymentID string `json:"payment_id,omitempty"`
|
||||
ShippingInfo InvoiceContactInfo `json:"shipping_info,omitempty"` // The recipient's shipping information.
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// used in Invoice
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-payments
|
||||
InvoicePayments struct {
|
||||
PaidAmount Money `json:"paid_amount,omitempty"`
|
||||
Transactions []InvoicePaymentDetails `json:"transactions,omitempty"`
|
||||
}
|
||||
|
||||
// used in InvoiceRecipientInfo
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-billing_info
|
||||
InvoiceBillingInfo struct {
|
||||
AdditionalInfo string `json:"additional_info,omitempty"`
|
||||
EmailAddress string `json:"email_address,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
Phones []InvoicerPhoneDetail `json:"phones,omitempty"` // invoice recipient's phone numbers.
|
||||
}
|
||||
// used in Invoice struct
|
||||
// Doc:
|
||||
InvoiceRecipientInfo struct {
|
||||
BillingInfo InvoiceBillingInfo `json:"billing_info,omitempty"` // billing information for the invoice recipient.
|
||||
ShippingInfo InvoiceContactInfo `json:"shipping_info,omitempty"` // recipient's shipping information.
|
||||
}
|
||||
|
||||
// used in InvoiceRefund struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-refund_detail
|
||||
InvoiceRefundDetails struct {
|
||||
Method string `json:"method"`
|
||||
RefundAmount Money `json:"amount,omitempty"`
|
||||
RefundDate string `json:"refund_date,omitempty"`
|
||||
RefundID string `json:"refund_id,omitempty"`
|
||||
RefundType string `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
// used in Invoice struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-refunds
|
||||
InvoiceRefund struct {
|
||||
RefundAmount Money `json:"refund_amount,omitempty"`
|
||||
RefundDetails []InvoiceRefundDetails `json:"transactions,omitempty"`
|
||||
}
|
||||
|
||||
// used in Invoice struct
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#definition-email_address
|
||||
InvoiceEmailAddress struct {
|
||||
EmailAddress string `json:"email_address,omitempty"`
|
||||
}
|
||||
|
||||
// to contain Invoice related fields
|
||||
// Doc: https://developer.paypal.com/docs/api/invoicing/v2/#invoices_get
|
||||
Invoice struct {
|
||||
AdditionalRecipients []InvoiceEmailAddress `json:"additional_recipients,omitempty"` // An array of one or more CC: emails to which notifications are sent.
|
||||
AmountSummary AmountSummaryDetail `json:"amount,omitempty"`
|
||||
Configuration InvoiceConfiguration `json:"configuration,omitempty"`
|
||||
Detail InvoiceDetail `json:"detail,omitempty"`
|
||||
DueAmount Money `json:"due_amount,omitempty"` // balance amount outstanding after payments.
|
||||
Gratuity Money `json:"gratuity,omitempty"` // amount paid by the payer as gratuity to the invoicer.
|
||||
ID string `json:"id,omitempty"`
|
||||
Invoicer InvoicerInfo `json:"invoicer,omitempty"`
|
||||
Items []InvoiceItem `json:"items,omitempty"`
|
||||
Links []Link `json:"links,omitempty"`
|
||||
ParentID string `json:"parent_id,omitempty"`
|
||||
Payments InvoicePayments `json:"payments,omitempty"`
|
||||
PrimaryRecipients []InvoiceRecipientInfo `json:"primary_recipients,omitempty"`
|
||||
Refunds InvoiceRefund `json:"refunds,omitempty"` // List of refunds against this invoice.
|
||||
Status string `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// Doc: https://developer.paypal.com/api/orders/v2/#definition-payment_method
|
||||
PaymentMethod struct {
|
||||
PayeePreferred PayeePreferred `json:"payee_preferred,omitempty"`
|
||||
|
|
Loading…
Reference in New Issue
Block a user