diff --git a/README.md b/README.md index da7c98e..2d8cfbb 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,28 @@ c, err := paypalsdk.NewClient("clietnid", "secret", paypalsdk.APIBaseSandBox) ``` // Redirect client to this URL with provided redirect URI and necessary scopes. It's necessary to retreive authorization_code -authCodeURL, err := c.GetAuthorizationCodeURL("https://example.com/redirect-uri", []string{"address"}) +authCodeURL, err := c.GetAuthorizationCodeURL("https://example.com/redirect-uri1", []string{"address"}) ``` ``` // When you will have authorization_code you can get an access_token -accessToken, err := c.GetAccessToken(authCode, "https://example.com/redirect-uri") +accessToken, err := c.GetAccessToken(authCode, "https://example.com/redirect-uri2") +``` + +``` +// Now we can create a paypal payment +amount := Amount{ + Total: 15.1111, + Currency: "USD", +} +paymentResult, err := c.CreateDirectPaypalPayment(amount, "http://example.com/redirect-uri3") + +// If paymentResult.ID is not empty and paymentResult.Links is also we can redirect user to approval page (paymentResult.Links[0]). After approval user will be redirected to return_url from Request with PaymentID + +// And the last step is to execute approved payment +// paymentID is returned via return_url +paymentID := "PAY-17S8410768582940NKEE66EQ" +// payerID is returned via return_url +payerID := "7E7MGXCWTTKK2" +executeResult, err := c.ExecuteApprovedPayment(paymentID, payerID) ``` diff --git a/payment.go b/payment.go index af8e2a5..66718d2 100644 --- a/payment.go +++ b/payment.go @@ -9,8 +9,10 @@ import ( ) // CreateDirectPaypalPayment sends request with payment -func (c *Client) CreateDirectPaypalPayment(amount Amount) (*PaymentResponse, error) { - buf := bytes.NewBuffer([]byte("{\"intent\":\"sale\",\"payer\":{\"payment_method\":\"paypal\"},\"transactions\":[{\"amount\":{\"total\":\"" + strconv.FormatFloat(amount.Total, 'f', 2, 64) + "\",\"currency\":\"" + amount.Currency + "\"}}]}")) +func (c *Client) CreateDirectPaypalPayment(amount Amount, redirectURI string) (*PaymentResponse, error) { + buf := bytes.NewBuffer([]byte("{\"intent\":\"sale\",\"payer\":{\"payment_method\":\"paypal\"}," + + "\"transactions\":[{\"amount\":{\"total\":\"" + strconv.FormatFloat(amount.Total, 'f', 2, 64) + + "\",\"currency\":\"" + amount.Currency + "\"}}],\"redirect_urls\":{\"return_url\":\"" + redirectURI + "\"}}")) req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/payment"), buf) if err != nil { return &PaymentResponse{}, err @@ -28,3 +30,24 @@ func (c *Client) CreateDirectPaypalPayment(amount Amount) (*PaymentResponse, err return &p, err } + +// ExecuteApprovedPayment executes approved payment +func (c *Client) ExecuteApprovedPayment(paymentID string, payerID string) (*ExecuteResponse, error) { + buf := bytes.NewBuffer([]byte("{\"payer_id\":\"" + payerID + "\"}")) + req, err := http.NewRequest("POST", fmt.Sprintf("%s%s", c.APIBase, "/v1/payments/payment/"+paymentID+"/execute"), buf) + if err != nil { + return &ExecuteResponse{}, err + } + + req.SetBasicAuth(c.ClientID, c.Secret) + req.Header.Set("Authorization", "Bearer "+c.Token.Token) + + e := ExecuteResponse{} + err = c.Send(req, &e) + + if e.ID == "" { + return &e, errors.New("Unable to execute payment with paymentID=" + paymentID) + } + + return &e, err +} diff --git a/payment_test.go b/payment_test.go index bb22717..5ebe9ec 100644 --- a/payment_test.go +++ b/payment_test.go @@ -15,7 +15,20 @@ func TestCreateDirectPaypalPayment(t *testing.T) { Currency: "USD", } - _, err := c.CreateDirectPaypalPayment(amount) + _, err := c.CreateDirectPaypalPayment(amount, "http://example.com") + + if err == nil { + t.Errorf("Error must be returned for invalid token") + } +} + +func TestExecuteApprovedPayment(t *testing.T) { + c, _ := NewClient("clid", "secret", APIBaseSandBox) + c.Token = &TokenResponse{ + Token: "invalidtoken", + } + + _, err := c.ExecuteApprovedPayment("PAY-6RV70583SB702805EKEYSZ6Y", "7E7MGXCWTTKK2") if err == nil { t.Errorf("Error must be returned for invalid token") diff --git a/types.go b/types.go index ab4d2ac..e73f5a6 100644 --- a/types.go +++ b/types.go @@ -49,7 +49,13 @@ type ( // PaymentResponse structure PaymentResponse struct { - ID string `json:"id"` + ID string `json:"id"` + Links []PaymentLink `json:"links"` + } + + // PaymentLink structure + PaymentLink struct { + Href string `json:"href"` } // Amount to pay @@ -57,6 +63,13 @@ type ( Currency string Total float64 } + + // ExecuteResponse structure + ExecuteResponse struct { + ID string `json:"id"` + Links []PaymentLink `json:"links"` + State string `json:"state"` + } ) // Error method implementation for ErrorResponse struct