From 4f66415fcdf280014b923290db31b702ef7d5170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hor=C3=A1k?= Date: Sat, 2 May 2020 14:43:30 +0000 Subject: [PATCH] Add transaction search /v1/reporting/transactions (#145) --- README.md | 1 + transaction_search.go | 97 +++++++++++++++++++++++++++++++++++++ types.go | 109 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+) create mode 100644 transaction_search.go diff --git a/README.md b/README.md index 0b2ee2f..e67ce86 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Currently supports **v2** only, if you want to use **v1**, use **v1.1.4** git ta * PATCH /v1/notifications/webhooks/**ID** * DELETE /v1/notifications/webhooks/**ID** * POST /v1/notifications/verify-webhook-signature + * POST /v1/reporting/transactions ### Missing endpoints It is possible that some endpoints are missing in this SDK Client, but you can use built-in **paypal** functions to perform a request: **NewClient -> NewRequest -> SendWithAuth** diff --git a/transaction_search.go b/transaction_search.go new file mode 100644 index 0000000..d74552e --- /dev/null +++ b/transaction_search.go @@ -0,0 +1,97 @@ +package paypal + +import ( + "fmt" + "strconv" + "time" +) + +type TransactionSearchRequest struct { + TransactionID *string + TransactionType *string + TransactionStatus *string + TransactionAmount *string + TransactionCurrency *string + StartDate time.Time + EndDate time.Time + PaymentInstrumentType *string + StoreID *string + TerminalID *string + Fields *string + BalanceAffectingRecordsOnly *string + PageSize *int + Page *int +} + +type TransactionSearchResponse struct { + TransactionDetails []SearchTransactionDetails `json:"transaction_details"` + AccountNumber string `json:"account_number"` + StartDate JSONTime `json:"start_date"` + EndDate JSONTime `json:"end_date"` + LastRefreshDatetime JSONTime `json:"last_refreshed_datetime"` + Page int `json:"page"` + TotalItems int `json:"total_items"` + TotalPages int `json:"total_pages"` + Links []Link `json:"links"` +} + +// ListTransactions - Use this to search PayPal transactions from the last 31 days. +// Endpoint: GET /v1/reporting/transactions +func (c *Client) ListTransactions(req *TransactionSearchRequest) (*TransactionSearchResponse, error) { + response := &TransactionSearchResponse{} + + r, err := c.NewRequest("GET", fmt.Sprintf("%s%s", c.APIBase, "/v1/reporting/transactions"), nil) + if err != nil { + return nil, err + } + + q := r.URL.Query() + + q.Add("start_date", req.StartDate.Format(time.RFC3339)) + q.Add("end_date", req.EndDate.Format(time.RFC3339)) + + if req.TransactionID != nil { + q.Add("transaction_id", *req.TransactionID) + } + if req.TransactionType != nil { + q.Add("transaction_type", *req.TransactionType) + } + if req.TransactionStatus != nil { + q.Add("transaction_status", *req.TransactionStatus) + } + if req.TransactionAmount != nil { + q.Add("transaction_amount", *req.TransactionAmount) + } + if req.TransactionCurrency != nil { + q.Add("transaction_currency", *req.TransactionCurrency) + } + if req.PaymentInstrumentType != nil { + q.Add("payment_instrument_type", *req.PaymentInstrumentType) + } + if req.StoreID != nil { + q.Add("store_id", *req.StoreID) + } + if req.TerminalID != nil { + q.Add("terminal_id", *req.TerminalID) + } + if req.Fields != nil { + q.Add("fields", *req.Fields) + } + if req.BalanceAffectingRecordsOnly != nil { + q.Add("balance_affecting_records_only", *req.BalanceAffectingRecordsOnly) + } + if req.PageSize != nil { + q.Add("page_size", strconv.Itoa(*req.PageSize)) + } + if req.Page != nil { + q.Add("page", strconv.Itoa(*req.Page)) + } + + r.URL.RawQuery = q.Encode() + + if err = c.SendWithAuth(r, response); err != nil { + return nil, err + } + + return response, nil +} diff --git a/types.go b/types.go index b12b67d..22638c0 100644 --- a/types.go +++ b/types.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "strings" "sync" "time" ) @@ -1082,6 +1083,106 @@ type ( Type string `json:"type"` Granted bool `json:"granted"` } + + SearchItemDetails struct { + ItemCode string `json:"item_code"` + ItemName string `json:"item_name"` + ItemDescription string `json:"item_description"` + ItemOptions string `json:"item_options"` + ItemQuantity string `json:"item_quantity"` + ItemUnitPrice Money `json:"item_unit_price"` + ItemAmount Money `json:"item_amount"` + DiscountAmount *Money `json:"discount_amount"` + AdjustmentAmount *Money `json:"adjustment_amount"` + GiftWrapAmount *Money `json:"gift_wrap_amount"` + TaxPercentage string `json:"tax_percentage"` + TaxAmounts []SearchTaxAmount `json:"tax_amounts"` + BasicShippingAmount *Money `json:"basic_shipping_amount"` + ExtraShippingAmount *Money `json:"extra_shipping_amount"` + HandlingAmount *Money `json:"handling_amount"` + InsuranceAmount *Money `json:"insurance_amount"` + TotalItemAmount Money `json:"total_item_amount"` + InvoiceNumber string `json:"invoice_number"` + CheckoutOptions []SearchCheckoutOption `json:"checkout_options"` + } + + SearchCheckoutOption struct { + CheckoutOptionName string `json:"checkout_option_name"` + CheckoutOptionValue string `json:"checkout_option_value"` + } + + SearchCartInfo struct { + ItemDetails []SearchItemDetails `json:"item_details"` + TaxInclusive *bool `json:"tax_inclusive"` + PayPalInvoiceID string `json:"paypal_invoice_id"` + } + + SearchShippingInfo struct { + Name string `json:"name"` + Method string `json:"method"` + Address Address `json:"address"` + SecondaryShippingAddress *Address `json:"secondary_shipping_address"` + } + + SearchPayerName struct { + GivenName string `json:"given_name"` + Surname string `json:"surname"` + } + + SearchPayerInfo struct { + AccountID string `json:"account_id"` + EmailAddress string `json:"email_address"` + PhoneNumber *PhoneWithTypeNumber `json:"phone_number"` + AddressStatus string `json:"address_status"` + PayerStatus string `json:"payer_status"` + PayerName SearchPayerName `json:"payer_name"` + CountryCode string `json:"country_code"` + Address *Address `json:"address"` + } + + SearchTaxAmount struct { + TaxAmount Money `json:"tax_amount"` + } + + SearchTransactionInfo struct { + PayPalAccountID string `json:"paypal_account_id"` + TransactionID string `json:"transaction_id"` + PayPalReferenceID string `json:"paypal_reference_id"` + PayPalReferenceIDType string `json:"paypal_reference_id_type"` + TransactionEventCode string `json:"transaction_event_code"` + TransactionInitiationDate JSONTime `json:"transaction_initiation_date"` + TransactionUpdatedDate JSONTime `json:"transaction_updated_date"` + TransactionAmount Money `json:"transaction_amount"` + FeeAmount *Money `json:"fee_amount"` + InsuranceAmount *Money `json:"insurance_amount"` + ShippingAmount *Money `json:"shipping_amount"` + ShippingDiscountAmount *Money `json:"shipping_discount_amount"` + ShippingTaxAmount *Money `json:"shipping_tax_amount"` + OtherAmount *Money `json:"other_amount"` + TipAmount *Money `json:"tip_amount"` + TransactionStatus string `json:"transaction_status"` + TransactionSubject string `json:"transaction_subject"` + PaymentTrackingID string `json:"payment_tracking_id"` + BankReferenceID string `json:"bank_reference_id"` + TransactionNote string `json:"transaction_note"` + EndingBalance *Money `json:"ending_balance"` + AvailableBalance *Money `json:"available_balance"` + InvoiceID string `json:"invoice_id"` + CustomField string `json:"custom_field"` + ProtectionEligibility string `json:"protection_eligibility"` + CreditTerm string `json:"credit_term"` + CreditTransactionalFee *Money `json:"credit_transactional_fee"` + CreditPromotionalFee *Money `json:"credit_promotional_fee"` + AnnualPercentageRate string `json:"annual_percentage_rate"` + PaymentMethodType string `json:"payment_method_type"` + } + + SearchTransactionDetails struct { + TransactionInfo SearchTransactionInfo `json:"transaction_info"` + PayerInfo *SearchPayerInfo `json:"payer_info"` + ShippingInfo *SearchShippingInfo `json:"shipping_info"` + CartInfo *SearchCartInfo `json:"cart_info"` + } ) // Error method implementation for ErrorResponse struct @@ -1095,6 +1196,14 @@ func (t JSONTime) MarshalJSON() ([]byte, error) { return []byte(stamp), nil } +// UnmarshalJSON for JSONTime, timezone offset is missing a colon ':" +func (t *JSONTime) UnmarshalJSON(b []byte) error { + s := strings.Trim(string(b), `"`) + nt, err := time.Parse("2006-01-02T15:04:05Z0700", s) + *t = JSONTime(nt) + return err +} + func (e *expirationTime) UnmarshalJSON(b []byte) error { var n json.Number err := json.Unmarshal(b, &n)