forked from go-packages/paypal
GetAuthorization, CreatePayment, tests, README
This commit is contained in:
parent
04214cbc33
commit
0c8d78e8a2
67
README.md
67
README.md
|
@ -6,10 +6,18 @@
|
||||||
* POST /v1/oauth2/token
|
* POST /v1/oauth2/token
|
||||||
* POST /v1/payments/payment
|
* POST /v1/payments/payment
|
||||||
* GET /v1/payments/payment/%ID%
|
* GET /v1/payments/payment/%ID%
|
||||||
- GET /v1/payments/payment
|
* GET /v1/payments/payment
|
||||||
|
* GET /v1/payments/authorization/%ID%
|
||||||
|
* POST /v1/payments/authorization/%ID%/capture
|
||||||
|
* POST /v1/payments/authorization/%ID%/void
|
||||||
|
* POST /v1/payments/authorization/%ID%/reauthorize
|
||||||
|
|
||||||
#### Create client
|
#### Create client
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/logpacker/paypalsdk"
|
||||||
|
```
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Create a client instance
|
// Create a client instance
|
||||||
c, err := paypalsdk.NewClient("clietnid", "secret", paypalsdk.APIBaseSandBox)
|
c, err := paypalsdk.NewClient("clietnid", "secret", paypalsdk.APIBaseSandBox)
|
||||||
|
@ -40,6 +48,39 @@ paymentResult, err := c.CreateDirectPaypalPayment(amount, redirectURI, cancelURI
|
||||||
// After approval user will be redirected to return_url from Request with PaymentID
|
// After approval user will be redirected to return_url from Request with PaymentID
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Create any payment
|
||||||
|
```go
|
||||||
|
p := paypalsdk.Payment{
|
||||||
|
Intent: "sale",
|
||||||
|
Payer: &paypalsdk.Payer{
|
||||||
|
PaymentMethod: "credit_card",
|
||||||
|
FundingInstruments: []paypalsdk.FundingInstrument{paypalsdk.FundingInstrument{
|
||||||
|
CreditCard: &paypalsdk.CreditCard{
|
||||||
|
Number: "4111111111111111",
|
||||||
|
Type: "visa",
|
||||||
|
ExpireMonth: "11",
|
||||||
|
ExpireYear: "2020",
|
||||||
|
CVV2: "777",
|
||||||
|
FirstName: "John",
|
||||||
|
LastName: "Doe",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
Transactions: []paypalsdk.Transaction{paypalsdk.Transaction{
|
||||||
|
Amount: &paypalsdk.Amount{
|
||||||
|
Currency: "USD",
|
||||||
|
Total: "200",
|
||||||
|
},
|
||||||
|
Description: "My Payment",
|
||||||
|
}},
|
||||||
|
RedirectURLs: &paypalsdk.RedirectURLs{
|
||||||
|
ReturnURL: "http://...",
|
||||||
|
CancelURL: "http://...",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
paymentResponse, err := client.CreatePayment(p)
|
||||||
|
```
|
||||||
|
|
||||||
#### Execute approved payment
|
#### Execute approved payment
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -64,3 +105,27 @@ payment, err := c.GetPayment(paymentID)
|
||||||
// Get all payments slice
|
// Get all payments slice
|
||||||
payments, err := c.GetPayments()
|
payments, err := c.GetPayments()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Get authorization by ID
|
||||||
|
|
||||||
|
```go
|
||||||
|
auth, err := c.GetAuthorization("AUTH-1")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Capture authorization
|
||||||
|
|
||||||
|
```go
|
||||||
|
capture, err := c.CaptureAuthorization("AUTH-1", &paypalsdk.Amount{Total: "200", Currency: "USD"}, true)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Void authorization
|
||||||
|
|
||||||
|
```go
|
||||||
|
auth, err := c.VoidAuthorization("AUTH-1")
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Reauthorize authorization
|
||||||
|
|
||||||
|
```go
|
||||||
|
auth, err := c.ReauthorizeAuthorization("AUTH-1", &paypalsdk.Amount{Total: "200", Currency: "USD"})
|
||||||
|
```
|
||||||
|
|
79
auth.go
79
auth.go
|
@ -27,3 +27,82 @@ func (c *Client) GetAccessToken() (*TokenResponse, error) {
|
||||||
|
|
||||||
return &t, err
|
return &t, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAuthorization returns an authorization by ID
|
||||||
|
func (c *Client) GetAuthorization(authID string) (*Authorization, error) {
|
||||||
|
buf := bytes.NewBuffer([]byte(""))
|
||||||
|
req, err := http.NewRequest("GET", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/authorization/"+authID), buf)
|
||||||
|
if err != nil {
|
||||||
|
return &Authorization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
auth := &Authorization{}
|
||||||
|
|
||||||
|
err = c.SendWithAuth(req, auth)
|
||||||
|
if err != nil {
|
||||||
|
return auth, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptureAuthorization captures and process an existing authorization.
|
||||||
|
// To use this method, the original payment must have Intent set to "authorize"
|
||||||
|
func (c *Client) CaptureAuthorization(authID string, a *Amount, isFinalCapture bool) (*Capture, error) {
|
||||||
|
isFinalStr := "false"
|
||||||
|
if isFinalCapture {
|
||||||
|
isFinalStr = "true"
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer([]byte("{\"amount\":{\"currency\":\"" + a.Currency + "\",\"total\":\"" + a.Total + "\"},\"is_final_capture\":" + isFinalStr + "}"))
|
||||||
|
req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/authorization/"+authID+"/capture"), buf)
|
||||||
|
if err != nil {
|
||||||
|
return &Capture{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
capture := &Capture{}
|
||||||
|
|
||||||
|
err = c.SendWithAuth(req, capture)
|
||||||
|
if err != nil {
|
||||||
|
return capture, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return capture, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VoidAuthorization voids a previously authorized payment
|
||||||
|
func (c *Client) VoidAuthorization(authID string) (*Authorization, error) {
|
||||||
|
buf := bytes.NewBuffer([]byte(""))
|
||||||
|
req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/authorization/"+authID+"/void"), buf)
|
||||||
|
if err != nil {
|
||||||
|
return &Authorization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
auth := &Authorization{}
|
||||||
|
|
||||||
|
err = c.SendWithAuth(req, auth)
|
||||||
|
if err != nil {
|
||||||
|
return auth, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReauthorizeAuthorization reauthorize a Paypal account payment.
|
||||||
|
// PayPal recommends to reauthorize payment after ~3 days
|
||||||
|
func (c *Client) ReauthorizeAuthorization(authID string, a *Amount) (*Authorization, error) {
|
||||||
|
buf := bytes.NewBuffer([]byte("{\"amount\":{\"currency\":\"" + a.Currency + "\",\"total\":\"" + a.Total + "\"}}"))
|
||||||
|
req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/authorization/"+authID+"/reauthorize"), buf)
|
||||||
|
if err != nil {
|
||||||
|
return &Authorization{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
auth := &Authorization{}
|
||||||
|
|
||||||
|
err = c.SendWithAuth(req, auth)
|
||||||
|
if err != nil {
|
||||||
|
return auth, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return auth, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
44
auth_test.go
44
auth_test.go
|
@ -8,3 +8,47 @@ func TestGetAccessToken(t *testing.T) {
|
||||||
c, _ := NewClient("clid", "secret", APIBaseSandBox)
|
c, _ := NewClient("clid", "secret", APIBaseSandBox)
|
||||||
c.GetAccessToken()
|
c.GetAccessToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetAuthorization(t *testing.T) {
|
||||||
|
c, _ := NewClient("clid", "secret", APIBaseSandBox)
|
||||||
|
c.GetAccessToken()
|
||||||
|
|
||||||
|
_, err := c.GetAuthorization("123")
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Error must be returned for invalid Auth ID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCaptureAuthorization(t *testing.T) {
|
||||||
|
c, _ := NewClient("clid", "secret", APIBaseSandBox)
|
||||||
|
c.GetAccessToken()
|
||||||
|
|
||||||
|
_, err := c.CaptureAuthorization("123", &Amount{Total: "200", Currency: "USD"}, true)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Error must be returned for invalid Auth ID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVoidAuthorization(t *testing.T) {
|
||||||
|
c, _ := NewClient("clid", "secret", APIBaseSandBox)
|
||||||
|
c.GetAccessToken()
|
||||||
|
|
||||||
|
_, err := c.VoidAuthorization("123")
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Error must be returned for invalid Auth ID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReauthorizeAuthorization(t *testing.T) {
|
||||||
|
c, _ := NewClient("clid", "secret", APIBaseSandBox)
|
||||||
|
c.GetAccessToken()
|
||||||
|
|
||||||
|
_, err := c.ReauthorizeAuthorization("123", &Amount{Total: "200", Currency: "USD"})
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Error must be returned for invalid Auth ID")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
20
client.go
20
client.go
|
@ -1,6 +1,7 @@
|
||||||
package paypalsdk
|
package paypalsdk
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
@ -92,11 +93,28 @@ func (c *Client) Send(req *http.Request, v interface{}) error {
|
||||||
// If the access token soon to be expired, it will try to get a new one before
|
// If the access token soon to be expired, it will try to get a new one before
|
||||||
// making the main request
|
// making the main request
|
||||||
func (c *Client) SendWithAuth(req *http.Request, v interface{}) error {
|
func (c *Client) SendWithAuth(req *http.Request, v interface{}) error {
|
||||||
req.Header.Set("Authorization", "Bearer "+c.Token.Token)
|
if c.Token != nil {
|
||||||
|
req.Header.Set("Authorization", "Bearer "+c.Token.Token)
|
||||||
|
}
|
||||||
|
|
||||||
return c.Send(req, v)
|
return c.Send(req, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewRequest constructs a request
|
||||||
|
// Convert payload to a JSON
|
||||||
|
func (c *Client) NewRequest(method, url string, payload interface{}) (*http.Request, error) {
|
||||||
|
var buf io.Reader
|
||||||
|
if payload != nil {
|
||||||
|
var b []byte
|
||||||
|
b, err := json.Marshal(&payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf = bytes.NewBuffer(b)
|
||||||
|
}
|
||||||
|
return http.NewRequest(method, url, buf)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) log(req *http.Request, resp *http.Response) {
|
func (c *Client) log(req *http.Request, resp *http.Response) {
|
||||||
if c.LogFile != "" {
|
if c.LogFile != "" {
|
||||||
os.OpenFile(c.LogFile, os.O_CREATE, 0755)
|
os.OpenFile(c.LogFile, os.O_CREATE, 0755)
|
||||||
|
|
|
@ -35,5 +35,41 @@ func main() {
|
||||||
fmt.Println("ERROR: " + err.Error())
|
fmt.Println("ERROR: " + err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p := paypalsdk.Payment{
|
||||||
|
Intent: "sale",
|
||||||
|
Payer: &paypalsdk.Payer{
|
||||||
|
PaymentMethod: "credit_card",
|
||||||
|
FundingInstruments: []paypalsdk.FundingInstrument{paypalsdk.FundingInstrument{
|
||||||
|
CreditCard: &paypalsdk.CreditCard{
|
||||||
|
Number: "4111111111111111",
|
||||||
|
Type: "visa",
|
||||||
|
ExpireMonth: "11",
|
||||||
|
ExpireYear: "2020",
|
||||||
|
CVV2: "777",
|
||||||
|
FirstName: "John",
|
||||||
|
LastName: "Doe",
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
Transactions: []paypalsdk.Transaction{paypalsdk.Transaction{
|
||||||
|
Amount: &paypalsdk.Amount{
|
||||||
|
Currency: "USD",
|
||||||
|
Total: "200",
|
||||||
|
},
|
||||||
|
Description: "My Payment",
|
||||||
|
}},
|
||||||
|
RedirectURLs: &paypalsdk.RedirectURLs{
|
||||||
|
ReturnURL: "http://...",
|
||||||
|
CancelURL: "http://...",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
paymentResponse, err := client.CreatePayment(p)
|
||||||
|
if err == nil {
|
||||||
|
fmt.Println("DEBUG: CreatedPaymentID=" + paymentResponse.Payment.ID)
|
||||||
|
} else {
|
||||||
|
fmt.Println("ERROR: " + err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
fmt.Println("OK")
|
fmt.Println("OK")
|
||||||
}
|
}
|
||||||
|
|
24
payment.go
24
payment.go
|
@ -12,7 +12,14 @@ type ListPaymentsResp struct {
|
||||||
Payments []Payment `json:"payments"`
|
Payments []Payment `json:"payments"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreatePaymentResp returned by CreatePayment
|
||||||
|
type CreatePaymentResp struct {
|
||||||
|
*Payment
|
||||||
|
Links []Links `json:"links"`
|
||||||
|
}
|
||||||
|
|
||||||
// CreateDirectPaypalPayment sends request with payment
|
// CreateDirectPaypalPayment sends request with payment
|
||||||
|
// CreatePayment is more common function for any kind of 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\":\"" + amount.Total +
|
"\"transactions\":[{\"amount\":{\"total\":\"" + amount.Total +
|
||||||
|
@ -39,6 +46,23 @@ func (c *Client) CreateDirectPaypalPayment(amount Amount, redirectURI string, ca
|
||||||
return &p, err
|
return &p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreatePayment creates a payment in Paypal
|
||||||
|
func (c *Client) CreatePayment(p Payment) (*CreatePaymentResp, error) {
|
||||||
|
req, err := c.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/payment"), p)
|
||||||
|
if err != nil {
|
||||||
|
return &CreatePaymentResp{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &CreatePaymentResp{}
|
||||||
|
|
||||||
|
err = c.SendWithAuth(req, response)
|
||||||
|
if err != nil {
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ExecuteApprovedPayment executes approved payment
|
// ExecuteApprovedPayment executes approved payment
|
||||||
func (c *Client) ExecuteApprovedPayment(paymentID string, payerID string) (*ExecuteResponse, error) {
|
func (c *Client) ExecuteApprovedPayment(paymentID string, payerID string) (*ExecuteResponse, error) {
|
||||||
buf := bytes.NewBuffer([]byte("{\"payer_id\":\"" + payerID + "\"}"))
|
buf := bytes.NewBuffer([]byte("{\"payer_id\":\"" + payerID + "\"}"))
|
||||||
|
|
35
types.go
35
types.go
|
@ -25,6 +25,33 @@ type (
|
||||||
Token *TokenResponse
|
Token *TokenResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Authorization maps to the authorization object
|
||||||
|
Authorization struct {
|
||||||
|
Amount *Amount `json:"amount,omitempty"`
|
||||||
|
CreateTime *time.Time `json:"create_time,omitempty"`
|
||||||
|
UpdateTime *time.Time `json:"update_time,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
ParentPayment string `json:"parent_payment,omitempty"`
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
ValidUntil *time.Time `json:"valid_until,omitempty"`
|
||||||
|
Links []Links `json:"links,omitempty"`
|
||||||
|
ClearingTime string `json:"clearing_time,omitempty"`
|
||||||
|
ProtectionEligibility string `json:"protection_eligibility,omitempty"`
|
||||||
|
ProtectionEligibilityType string `json:"protection_eligibility_type,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture maps to the capture object
|
||||||
|
Capture struct {
|
||||||
|
Amount *Amount `json:"amount,omitempty"`
|
||||||
|
IsFinalCapture bool `json:"is_final_capture"`
|
||||||
|
CreateTime *time.Time `json:"create_time,omitempty"`
|
||||||
|
UpdateTime *time.Time `json:"update_time,omitempty"`
|
||||||
|
State string `json:"state,omitempty"`
|
||||||
|
ParentPayment string `json:"parent_payment,omitempty"`
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Links []Links `json:"links,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Address maps to address object
|
// Address maps to address object
|
||||||
Address struct {
|
Address struct {
|
||||||
Line1 string `json:"line1"`
|
Line1 string `json:"line1"`
|
||||||
|
@ -135,6 +162,14 @@ type (
|
||||||
CancelURL string `json:"cancel_url,omitempty"`
|
CancelURL string `json:"cancel_url,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Links maps to links object
|
||||||
|
Links struct {
|
||||||
|
Href string `json:"href"`
|
||||||
|
Rel string `json:"rel"`
|
||||||
|
Method string `json:"method"`
|
||||||
|
Enctype string `json:"enctype"`
|
||||||
|
}
|
||||||
|
|
||||||
// Payment maps to payment object
|
// Payment maps to payment object
|
||||||
Payment struct {
|
Payment struct {
|
||||||
Intent string `json:"intent"`
|
Intent string `json:"intent"`
|
||||||
|
|
Loading…
Reference in New Issue
Block a user