GetPayment, GetPayments

This commit is contained in:
Aliaksandr Pliutau 2015-11-25 17:30:25 +07:00
parent 03bfbaface
commit fcccd51161
5 changed files with 234 additions and 7 deletions

View File

@ -21,7 +21,7 @@ amount := Amount{
Total: 15.1111, Total: 15.1111,
Currency: "USD", Currency: "USD",
} }
paymentResult, err := c.CreateDirectPaypalPayment(amount, "http://example.com/redirect-uri") paymentResult, err := c.CreateDirectPaypalPayment(amount, "http://example.com/redirect-uri", "http://example.com/cancel-uri", "Description for this payment")
// If paymentResult.ID is not empty and paymentResult.Links is also // If paymentResult.ID is not empty and paymentResult.Links is also
// we can redirect user to approval page (paymentResult.Links[0]). // we can redirect user to approval page (paymentResult.Links[0]).
@ -36,3 +36,13 @@ paymentID := "PAY-17S8410768582940NKEE66EQ"
payerID := "7E7MGXCWTTKK2" payerID := "7E7MGXCWTTKK2"
executeResult, err := c.ExecuteApprovedPayment(paymentID, payerID) executeResult, err := c.ExecuteApprovedPayment(paymentID, payerID)
``` ```
```go
// Get created payment info
payment, err := c.GetPayment(paymentID)
```
```go
// Get all payments slice
payments, err := c.GetPayments()
```

View File

@ -2,6 +2,7 @@ package main
import ( import (
"paypalsdk" "paypalsdk"
"strconv"
"fmt" "fmt"
"os" "os"
@ -15,4 +16,24 @@ func main() {
fmt.Println("ERROR: " + err.Error()) fmt.Println("ERROR: " + err.Error())
os.Exit(1) os.Exit(1)
} }
token, err := client.GetAccessToken()
if err == nil {
fmt.Println("DEBUG: AccessToken=" + token.Token)
} else {
fmt.Println("ERROR: " + err.Error())
os.Exit(1)
}
payment, err := client.GetPayment("PAY-TEST-123")
fmt.Println("DEBUG: PaymentID=" + payment.ID)
payments, err := client.GetPayments()
if err == nil {
fmt.Println("DEBUG: PaymentsCount=" + strconv.Itoa(len(payments)))
} else {
fmt.Println("ERROR: " + err.Error())
os.Exit(1)
}
fmt.Println("OK")
} }

View File

@ -5,13 +5,17 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"strconv"
) )
// ListPaymentsResp slice of payments
type ListPaymentsResp struct {
Payments []Payment `json:"payments"`
}
// CreateDirectPaypalPayment sends request with payment // CreateDirectPaypalPayment sends request with payment
func (c *Client) CreateDirectPaypalPayment(amount Amount, redirectURI string, cancelURI string, description string) (*PaymentResponse, error) { func (c *Client) CreateDirectPaypalPayment(amount Amount, redirectURI string, cancelURI string, description string) (*PaymentResponse, error) {
buf := bytes.NewBuffer([]byte("{\"intent\":\"sale\",\"payer\":{\"payment_method\":\"paypal\"}," + buf := bytes.NewBuffer([]byte("{\"intent\":\"sale\",\"payer\":{\"payment_method\":\"paypal\"}," +
"\"transactions\":[{\"amount\":{\"total\":\"" + strconv.FormatFloat(amount.Total, 'f', 2, 64) + "\"transactions\":[{\"amount\":{\"total\":\"" + amount.Total +
"\",\"currency\":\"" + amount.Currency + "\"},\"description\":\"" + description + "\"}],\"redirect_urls\":{\"return_url\":\"" + "\",\"currency\":\"" + amount.Currency + "\"},\"description\":\"" + description + "\"}],\"redirect_urls\":{\"return_url\":\"" +
redirectURI + "\",\"cancel_url\":\"" + cancelURI + "\"}}")) redirectURI + "\",\"cancel_url\":\"" + cancelURI + "\"}}"))
req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/payment"), buf) req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/payment"), buf)
@ -24,6 +28,9 @@ func (c *Client) CreateDirectPaypalPayment(amount Amount, redirectURI string, ca
p := PaymentResponse{} p := PaymentResponse{}
err = c.SendWithAuth(req, &p) err = c.SendWithAuth(req, &p)
if err != nil {
return &p, err
}
if p.ID == "" { if p.ID == "" {
return &p, errors.New("Unable to create payment with this access token") return &p, errors.New("Unable to create payment with this access token")
@ -45,6 +52,9 @@ func (c *Client) ExecuteApprovedPayment(paymentID string, payerID string) (*Exec
e := ExecuteResponse{} e := ExecuteResponse{}
err = c.SendWithAuth(req, &e) err = c.SendWithAuth(req, &e)
if err != nil {
return &e, err
}
if e.ID == "" { if e.ID == "" {
return &e, errors.New("Unable to execute payment with paymentID=" + paymentID) return &e, errors.New("Unable to execute payment with paymentID=" + paymentID)
@ -52,3 +62,41 @@ func (c *Client) ExecuteApprovedPayment(paymentID string, payerID string) (*Exec
return &e, err return &e, err
} }
// GetPayment gets a payment from PayPal
func (c *Client) GetPayment(paymentID string) (*Payment, error) {
p := Payment{}
req, err := http.NewRequest("GET", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/payment/"+paymentID), nil)
if err != nil {
return &p, err
}
err = c.SendWithAuth(req, &p)
if err != nil {
return &p, err
}
if p.ID == "" {
return &p, errors.New("Unable to get payment with paymentID=" + paymentID)
}
return &p, nil
}
// GetPayments retrieve payments resources from Paypal
func (c *Client) GetPayments() ([]Payment, error) {
var p ListPaymentsResp
req, err := http.NewRequest("GET", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/payment/"), nil)
if err != nil {
return p.Payments, err
}
err = c.SendWithAuth(req, &p)
if err != nil {
return p.Payments, err
}
return p.Payments, nil
}

View File

@ -11,17 +11,43 @@ func TestCreateDirectPaypalPayment(t *testing.T) {
} }
amount := Amount{ amount := Amount{
Total: 15.1111, Total: "15.1111",
Currency: "USD", Currency: "USD",
} }
_, err := c.CreateDirectPaypalPayment(amount, "http://example.com", "http://example.com") _, err := c.CreateDirectPaypalPayment(amount, "http://example.com", "http://example.com", "test payment")
if err == nil { if err == nil {
t.Errorf("Error must be returned for invalid token") t.Errorf("Error must be returned for invalid token")
} }
} }
func TestGetPayment(t *testing.T) {
c, _ := NewClient("clid", "secret", APIBaseSandBox)
c.Token = &TokenResponse{
Token: "invalidtoken",
}
_, err := c.GetPayment("PAY-TEST-123")
if err == nil {
t.Errorf("Error must be returned for invalid ID")
}
}
func TestGetPayments(t *testing.T) {
c, _ := NewClient("clid", "secret", APIBaseSandBox)
c.Token = &TokenResponse{
Token: "invalidtoken",
}
payments, _ := c.GetPayments()
if len(payments) != 0 {
t.Errorf("0 payments must be returned for unautgorized request")
}
}
func TestExecuteApprovedPayment(t *testing.T) { func TestExecuteApprovedPayment(t *testing.T) {
c, _ := NewClient("clid", "secret", APIBaseSandBox) c, _ := NewClient("clid", "secret", APIBaseSandBox)
c.Token = &TokenResponse{ c.Token = &TokenResponse{

126
types.go
View File

@ -3,6 +3,7 @@ package paypalsdk
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"time"
) )
const ( const (
@ -24,6 +25,48 @@ type (
Token *TokenResponse Token *TokenResponse
} }
// Address maps to address object
Address struct {
Line1 string `json:"line1"`
Line2 string `json:"line2,omitempty"`
City string `json:"city"`
CountryCode string `json:"country_code"`
PostalCode string `json:"postal_code,omitempty"`
State string `json:"state,omitempty"`
Phone string `json:"phone,omitempty"`
}
// CreditCard maps to credit_card object
CreditCard struct {
ID string `json:"id,omitempty"`
PayerID string `json:"payer_id,omitempty"`
Number string `json:"number"`
Type string `json:"type"`
ExpireMonth string `json:"expire_month"`
ExpireYear string `json:"expire_year"`
CVV2 string `json:"cvv2,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
BillingAddress *Address `json:"billing_address,omitempty"`
State string `json:"state,omitempty"`
ValidUntil string `json:"valid_until,omitempty"`
}
// CreditCardToken maps to credit_card_token object
CreditCardToken struct {
CreditCardID string `json:"credit_card_id"`
PayerID string `json:"payer_id,omitempty"`
Last4 string `json:"last4,omitempty"`
ExpireYear string `json:"expire_year,omitempty"`
ExpireMonth string `json:"expire_month,omitempty"`
}
// FundingInstrument maps to funding_instrument object
FundingInstrument struct {
CreditCard *CreditCard `json:"credit_card,omitempty"`
CreditCardToken *CreditCardToken `json:"credit_card_token,omitempty"`
}
// TokenResponse maps to the API response for the /oauth2/token endpoint // TokenResponse maps to the API response for the /oauth2/token endpoint
TokenResponse struct { TokenResponse struct {
RefreshToken string `json:"refresh_token"` RefreshToken string `json:"refresh_token"`
@ -53,6 +96,85 @@ type (
Links []PaymentLink `json:"links"` Links []PaymentLink `json:"links"`
} }
// Payer maps to payer object
Payer struct {
PaymentMethod string `json:"payment_method"`
FundingInstruments []FundingInstrument `json:"funding_instruments,omitempty"`
PayerInfo *PayerInfo `json:"payer_info,omitempty"`
Status string `json:"payer_status,omitempty"`
}
// PayerInfo maps to payer_info object
PayerInfo struct {
Email string `json:"email,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
PayerID string `json:"payer_id,omitempty"`
Phone string `json:"phone,omitempty"`
ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
TaxIDType string `json:"tax_id_type,omitempty"`
TaxID string `json:"tax_id,omitempty"`
}
// ShippingAddress maps to shipping_address object
ShippingAddress struct {
RecipientName string `json:"recipient_name,omitempty"`
Type string `json:"type,omitempty"`
Line1 string `json:"line1"`
Line2 string `json:"line2,omitempty"`
City string `json:"city"`
CountryCode string `json:"country_code"`
PostalCode string `json:"postal_code,omitempty"`
State string `json:"state,omitempty"`
Phone string `json:"phone,omitempty"`
}
// RedirectURLs maps to redirect_urls object
RedirectURLs struct {
ReturnURL string `json:"return_url,omitempty"`
CancelURL string `json:"cancel_url,omitempty"`
}
// Payment maps to payment object
Payment struct {
Intent string `json:"intent"`
Payer *Payer `json:"payer"`
Transactions []Transaction `json:"transactions"`
RedirectURLs *RedirectURLs `json:"redirect_urls,omitempty"`
ID string `json:"id,omitempty"`
CreateTime *time.Time `json:"create_time,omitempty"`
State string `json:"state,omitempty"`
UpdateTime *time.Time `json:"update_time,omitempty"`
ExperienceProfileID string `json:"experience_profile_id,omitempty"`
}
// Item maps to item object
Item struct {
Quantity int `json:"quantity"`
Name string `json:"name"`
Price string `json:"price"`
Currency string `json:"currency"`
SKU string `json:"sku,omitempty"`
Description string `json:"description,omitempty"`
Tax string `json:"tax,omitempty"`
}
// ItemList maps to item_list object
ItemList struct {
Items []Item `json:"items,omitempty"`
ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
}
// Transaction maps to transaction object
Transaction struct {
Amount *Amount `json:"amount"`
Description string `json:"description,omitempty"`
ItemList *ItemList `json:"item_list,omitempty"`
InvoiceNumber string `json:"invoice_number,omitempty"`
Custom string `json:"custom,omitempty"`
SoftDescriptor string `json:"soft_descriptor,omitempty"`
}
// PaymentLink structure // PaymentLink structure
PaymentLink struct { PaymentLink struct {
Href string `json:"href"` Href string `json:"href"`
@ -61,8 +183,8 @@ type (
// Amount to pay // Amount to pay
Amount struct { Amount struct {
Currency string Currency string `json:"currency"`
Total float64 Total string `json:"total"`
} }
// ExecuteResponse structure // ExecuteResponse structure