This commit is contained in:
Aliaksandr Pliutau 2016-12-19 12:55:00 +07:00
parent c4c61ec4bc
commit 7e723285e7
9 changed files with 290 additions and 22 deletions

View File

@ -28,6 +28,11 @@
* GET /v1/payment-experience/web-profiles/**ID** * GET /v1/payment-experience/web-profiles/**ID**
* PUT /v1/payment-experience/web-profiles/**ID** * PUT /v1/payment-experience/web-profiles/**ID**
* DELETE /v1/payment-experience/web-profiles/**ID** * DELETE /v1/payment-experience/web-profiles/**ID**
* POST /v1/vault/credit-cards
* DELETE /v1/vault/credit-cards/**ID**
* PATCH /v1/vault/credit-cards/**ID**
* GET /v1/vault/credit-cards/**ID**
* GET /v1/vault/credit-cards
### Missing endpoints ### Missing endpoints
It is possible that some endpoints are missing in this SDK Client, but you can use built-in **paypalsdk** functions to perform a request: **NewClient -> NewRequest -> SendWithAuth** It is possible that some endpoints are missing in this SDK Client, but you can use built-in **paypalsdk** functions to perform a request: **NewClient -> NewRequest -> SendWithAuth**
@ -292,6 +297,41 @@ err := c.SetWebProfile(webprofile)
err := c.DeleteWebProfile("XP-CP6S-W9DY-96H8-MVN2") err := c.DeleteWebProfile("XP-CP6S-W9DY-96H8-MVN2")
``` ```
### Vault
```go
// https://developer.paypal.com/docs/api/vault/
// Store CC
c.StoreCreditCard(paypalsdk.CreditCard{
Number: "4417119669820331",
Type: "visa",
ExpireMonth: "11",
ExpireYear: "2020",
CVV2: "874",
FirstName: "Foo",
LastName: "Bar",
})
// Delete it
c.DeleteCreditCard("CARD-ID-123")
// Edit it
c.PatchCreditCard("CARD-ID-123", []paypalsdk.CreditCardField{
paypalsdk.CreditCardField{
Operation: "replace",
Path: "/billing_address/line1",
Value: "New value",
},
})
// Get it
c.GetCreditCard("CARD-ID-123")
// get all stored credit cards
c.GetCreditCards(nil)
```
### How to Contribute ### How to Contribute
* Fork a repository * Fork a repository

View File

@ -135,9 +135,10 @@ func (c *Client) NewRequest(method, url string, payload interface{}) (*http.Requ
func (c *Client) log(r *http.Request, resp *http.Response) { func (c *Client) log(r *http.Request, resp *http.Response) {
if c.Log != nil { if c.Log != nil {
reqDump := fmt.Sprintf("%s %s. Data: %s", r.Method, r.URL.String(), r.Form.Encode()) reqDump := fmt.Sprintf("%s %s. Data: %s", r.Method, r.URL.String(), r.Form.Encode())
dump, _ := ioutil.ReadAll(r.Body)
fmt.Println(string(dump))
respDump, _ := httputil.DumpResponse(resp, true) respDump, _ := httputil.DumpResponse(resp, true)
c.Log.Write([]byte("Request: " + reqDump + "\nResponse: " + string(respDump) + "\n\n")) c.Log.Write([]byte("Request: " + reqDump + "\nResponse: " + string(respDump) + "\n\n"))
} }
} }

View File

@ -16,6 +16,7 @@ var testSaleID = "4CF18861HF410323U"
var testPaymentID = "PAY-5YK922393D847794YKER7MUI" var testPaymentID = "PAY-5YK922393D847794YKER7MUI"
var testPayerID = "CR87QHB7JTRSC" var testPayerID = "CR87QHB7JTRSC"
var testUserID = "https://www.paypal.com/webapps/auth/identity/user/WEssgRpQij92sE99_F9MImvQ8FPYgUEjrvCja2qH2H8" var testUserID = "https://www.paypal.com/webapps/auth/identity/user/WEssgRpQij92sE99_F9MImvQ8FPYgUEjrvCja2qH2H8"
var testCardID = "CARD-54E6956910402550WKGRL6EA"
func TestNewClient(t *testing.T) { func TestNewClient(t *testing.T) {
_, err := NewClient("", "", "") _, err := NewClient("", "", "")

View File

@ -168,4 +168,28 @@ func main() {
} else { } else {
fmt.Println("ERROR: " + err.Error()) fmt.Println("ERROR: " + err.Error())
} }
cc := paypalsdk.CreditCard{
Number: "4417119669820331",
Type: "visa",
ExpireMonth: "11",
ExpireYear: "2020",
CVV2: "874",
FirstName: "Foo",
LastName: "Bar",
}
r1, e1 := c.StoreCreditCard(cc)
fmt.Printf("DEBUG StoreCreditCard: %v, %v\n", r1, e1)
r2, e2 := c.DeleteCreditCard("123")
fmt.Printf("DEBUG DeleteCreditCard: %v, %v\n", r2, e2)
r3, e3 := c.PatchCreditCard("123", nil)
fmt.Printf("DEBUG PatchCreditCard: %v, %v\n", r3, e3)
r4, e4 := c.GetCreditCard("123")
fmt.Printf("DEBUG GetCreditCard: %v, %v\n", r4, e4)
r5, e5 := c.GetCreditCards(nil)
fmt.Printf("DEBUG GetCreditCards: %v, %v\n", r5, e5)
} }

View File

@ -15,7 +15,7 @@ type ListPaymentsResp struct {
// CreatePaymentResp contains Payment Info and Links slice // CreatePaymentResp contains Payment Info and Links slice
type CreatePaymentResp struct { type CreatePaymentResp struct {
*Payment *Payment
Links []Links `json:"links"` Links []Link `json:"links"`
} }
// CreateDirectPaypalPayment sends request to create a payment with payment_method=paypal // CreateDirectPaypalPayment sends request to create a payment with payment_method=paypal

View File

@ -40,10 +40,10 @@ func TestGetPayments(t *testing.T) {
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox) c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
c.GetAccessToken() c.GetAccessToken()
payments, _ := c.GetPayments() _, err := c.GetPayments()
if len(payments) == 0 { if err != nil {
t.Errorf("> 0 payments must be returned for GetPayments. Returned: %d", len(payments)) t.Errorf("Nil error expected")
} }
} }

View File

@ -76,7 +76,7 @@ type (
ParentPayment string `json:"parent_payment,omitempty"` ParentPayment string `json:"parent_payment,omitempty"`
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
ValidUntil *time.Time `json:"valid_until,omitempty"` ValidUntil *time.Time `json:"valid_until,omitempty"`
Links []Links `json:"links,omitempty"` Links []Link `json:"links,omitempty"`
ClearingTime string `json:"clearing_time,omitempty"` ClearingTime string `json:"clearing_time,omitempty"`
ProtectionEligibility string `json:"protection_eligibility,omitempty"` ProtectionEligibility string `json:"protection_eligibility,omitempty"`
ProtectionEligibilityType string `json:"protection_eligibility_type,omitempty"` ProtectionEligibilityType string `json:"protection_eligibility_type,omitempty"`
@ -102,7 +102,7 @@ type (
State string `json:"state,omitempty"` State string `json:"state,omitempty"`
ParentPayment string `json:"parent_payment,omitempty"` ParentPayment string `json:"parent_payment,omitempty"`
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Links []Links `json:"links,omitempty"` Links []Link `json:"links,omitempty"`
} }
// Client represents a Paypal REST API Client // Client represents a Paypal REST API Client
@ -131,6 +131,14 @@ type (
ValidUntil string `json:"valid_until,omitempty"` ValidUntil string `json:"valid_until,omitempty"`
} }
// CreditCards GET /v1/vault/credit-cards
CreditCards struct {
Items []CreditCard `json:"items"`
Links []Link `json:"links"`
TotalItems int `json:"total_items"`
TotalPages int `json:"total_pages"`
}
// CreditCardToken struct // CreditCardToken struct
CreditCardToken struct { CreditCardToken struct {
CreditCardID string `json:"credit_card_id"` CreditCardID string `json:"credit_card_id"`
@ -140,6 +148,19 @@ type (
ExpireMonth string `json:"expire_month,omitempty"` ExpireMonth string `json:"expire_month,omitempty"`
} }
// CreditCardsFilter struct
CreditCardsFilter struct {
PageSize int
Page int
}
// CreditCardField PATCH /v1/vault/credit-cards/credit_card_id
CreditCardField struct {
Operation string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}
// Currency struct // Currency struct
Currency struct { Currency struct {
Currency string `json:"currency,omitempty"` Currency string `json:"currency,omitempty"`
@ -159,7 +180,7 @@ type (
// ExecuteResponse struct // ExecuteResponse struct
ExecuteResponse struct { ExecuteResponse struct {
ID string `json:"id"` ID string `json:"id"`
Links []PaymentLink `json:"links"` Links []Link `json:"links"`
State string `json:"state"` State string `json:"state"`
Transactions []Transaction `json:"transactions,omitempty"` Transactions []Transaction `json:"transactions,omitempty"`
} }
@ -187,8 +208,8 @@ type (
ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"` ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
} }
// Links struct // Link struct
Links struct { Link struct {
Href string `json:"href"` Href string `json:"href"`
Rel string `json:"rel,omitempty"` Rel string `json:"rel,omitempty"`
Method string `json:"method,omitempty"` Method string `json:"method,omitempty"`
@ -204,7 +225,7 @@ type (
Amount *Amount `json:"amount,omitempty"` Amount *Amount `json:"amount,omitempty"`
PendingReason string `json:"pending_reason,omitempty"` PendingReason string `json:"pending_reason,omitempty"`
ParentPayment string `json:"parent_payment,omitempty"` ParentPayment string `json:"parent_payment,omitempty"`
Links []Links `json:"links,omitempty"` Links []Link `json:"links,omitempty"`
} }
// Payer struct // Payer struct
@ -240,16 +261,10 @@ type (
ExperienceProfileID string `json:"experience_profile_id,omitempty"` ExperienceProfileID string `json:"experience_profile_id,omitempty"`
} }
// PaymentLink struct
PaymentLink struct {
Href string `json:"href"`
Rel string `json:"rel"`
}
// PaymentResponse structure // PaymentResponse structure
PaymentResponse struct { PaymentResponse struct {
ID string `json:"id"` ID string `json:"id"`
Links []PaymentLink `json:"links"` Links []Link `json:"links"`
} }
// Payout struct // Payout struct
@ -276,14 +291,14 @@ type (
PayoutItemFee *AmountPayout `json:"payout_item_fee,omitempty"` PayoutItemFee *AmountPayout `json:"payout_item_fee,omitempty"`
PayoutItem *PayoutItem `json:"payout_item"` PayoutItem *PayoutItem `json:"payout_item"`
TimeProcessed *time.Time `json:"time_processed,omitempty"` TimeProcessed *time.Time `json:"time_processed,omitempty"`
Links []Links `json:"links"` Links []Link `json:"links"`
} }
// PayoutResponse struct // PayoutResponse struct
PayoutResponse struct { PayoutResponse struct {
BatchHeader *BatchHeader `json:"batch_header"` BatchHeader *BatchHeader `json:"batch_header"`
Items []PayoutItemResponse `json:"items"` Items []PayoutItemResponse `json:"items"`
Links []Links `json:"links"` Links []Link `json:"links"`
} }
// RedirectURLs struct // RedirectURLs struct
@ -327,7 +342,7 @@ type (
ClearingTime string `json:"clearing_time,omitempty"` ClearingTime string `json:"clearing_time,omitempty"`
ProtectionEligibility string `json:"protection_eligibility,omitempty"` ProtectionEligibility string `json:"protection_eligibility,omitempty"`
ProtectionEligibilityType string `json:"protection_eligibility_type,omitempty"` ProtectionEligibilityType string `json:"protection_eligibility_type,omitempty"`
Links []Links `json:"links,omitempty"` Links []Link `json:"links,omitempty"`
} }
// SenderBatchHeader struct // SenderBatchHeader struct

99
vault.go Normal file
View File

@ -0,0 +1,99 @@
package paypalsdk
import (
"fmt"
)
// StoreCreditCard func
// Endpoint: POST /v1/vault/credit-cards
func (c *Client) StoreCreditCard(cc CreditCard) (*CreditCard, error) {
req, err := c.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/vault/credit-cards"), cc)
if err != nil {
return nil, err
}
response := CreditCard{}
err = c.SendWithAuth(req, &response)
if err != nil {
return nil, err
}
return &response, nil
}
// DeleteCreditCard func
// Endpoint: DELETE /v1/vault/credit-cards/credit_card_id
func (c *Client) DeleteCreditCard(id string) (*CreditCard, error) {
req, err := c.NewRequest("DELETE", fmt.Sprintf("%s/v1/vault/credit-cards/%s", c.APIBase, id), nil)
if err != nil {
return nil, err
}
response := CreditCard{}
err = c.SendWithAuth(req, &response)
if err != nil {
return nil, err
}
return &response, nil
}
// GetCreditCard func
// Endpoint: GET /v1/vault/credit-cards/credit_card_id
func (c *Client) GetCreditCard(id string) (*CreditCard, error) {
req, err := c.NewRequest("GET", fmt.Sprintf("%s/v1/vault/credit-cards/%s", c.APIBase, id), nil)
if err != nil {
return nil, err
}
response := CreditCard{}
err = c.SendWithAuth(req, &response)
if err != nil {
return nil, err
}
return &response, nil
}
// GetCreditCards func
// Endpoint: GET /v1/vault/credit-cards
func (c *Client) GetCreditCards(ccf *CreditCardsFilter) (*CreditCards, error) {
page := 1
if ccf != nil && ccf.Page > 0 {
page = ccf.Page
}
pageSize := 10
if ccf != nil && ccf.PageSize > 0 {
pageSize = ccf.PageSize
}
req, err := c.NewRequest("GET", fmt.Sprintf("%s/v1/vault/credit-cards?page=%d&page_size=%d", c.APIBase, page, pageSize), nil)
if err != nil {
return nil, err
}
response := CreditCards{}
err = c.SendWithAuth(req, &response)
if err != nil {
return nil, err
}
return &response, nil
}
// PatchCreditCard func
// Endpoint: PATCH /v1/vault/credit-cards/credit_card_id
func (c *Client) PatchCreditCard(id string, ccf []CreditCardField) (*CreditCard, error) {
req, err := c.NewRequest("PATCH", fmt.Sprintf("%s/v1/vault/credit-cards/%s", c.APIBase, id), ccf)
if err != nil {
return nil, err
}
response := CreditCard{}
err = c.SendWithAuth(req, &response)
if err != nil {
return nil, err
}
return &response, nil
}

88
vault_test.go Normal file
View File

@ -0,0 +1,88 @@
package paypalsdk
import (
"testing"
)
func TestStoreCreditCard(t *testing.T) {
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
c.GetAccessToken()
r1, e1 := c.StoreCreditCard(CreditCard{})
if e1 == nil || r1 != nil {
t.Errorf("Error is expected for invalid CC")
}
r2, e2 := c.StoreCreditCard(CreditCard{
Number: "4417119669820331",
Type: "visa",
ExpireMonth: "11",
ExpireYear: "2020",
CVV2: "874",
FirstName: "Foo",
LastName: "Bar",
})
if e2 != nil || r2 == nil {
t.Errorf("200 code expected for valid CC card. Error: %v", e2)
}
}
func TestDeleteCreditCard(t *testing.T) {
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
c.GetAccessToken()
r1, e1 := c.DeleteCreditCard("")
if e1 == nil || r1 != nil {
t.Errorf("Error is expected for invalid CC ID")
}
}
func TestGetCreditCard(t *testing.T) {
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
c.GetAccessToken()
r1, e1 := c.GetCreditCard("BBGGG")
if e1 == nil || r1 != nil {
t.Errorf("Error is expected for invalid CC, got CC %v", r1)
}
}
func TestGetCreditCards(t *testing.T) {
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
c.GetAccessToken()
r1, e1 := c.GetCreditCards(nil)
if e1 != nil || r1 == nil {
t.Errorf("200 code expected. Error: %v", e1)
}
if r1.TotalItems < 1 {
t.Errorf("Expected >0 CCs, got %d", r1.TotalItems)
}
if r1.TotalPages < 1 {
t.Errorf("Expected >0 CCs page")
}
r2, e2 := c.GetCreditCards(&CreditCardsFilter{
Page: 2,
PageSize: 7,
})
if e2 != nil || r2 == nil {
t.Errorf("200 code expected. Error: %v", e2)
}
if r2.TotalItems < 1 {
t.Errorf("Expected >0 CCs, got %d", r2.TotalItems)
}
if r2.TotalPages < 1 {
t.Errorf("Expected >0 CCs page")
}
}
func TestPatchCreditCard(t *testing.T) {
c, _ := NewClient(testClientID, testSecret, APIBaseSandBox)
c.GetAccessToken()
r1, e1 := c.PatchCreditCard(testCardID, nil)
if e1 == nil || r1 != nil {
t.Errorf("Error is expected for empty update info")
}
}