Skip to content

I have made a few stylistic changes and fixed some errors. #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# PayPal Rest Api in Go
# PayPal Rest API in Go

## Tests

Expand All @@ -9,4 +9,4 @@ The Tests need your PayPal credentials (clientId ans secret) in the env vars:

## Status

Right now it is just a technical test.
This fork is intended to make a test PayPal transaction which will be used in another project.
87 changes: 50 additions & 37 deletions pp.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Package main provides ...

package main

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"testing"
"io/ioutil"
"net/http"
"os"
Expand All @@ -17,10 +18,10 @@ import (

type (
TokenResponse struct {
Scope string // "https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.*",
Access_token string // "EEwJ6tF9x5WCIZDYzyZGaz6Khbw7raYRIBV_WxVvgmsG",
Token_type string // "Bearer",
App_id string // "APP-6XR95014BA15863X",
Scope string // "https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.*"
Access_token string // "EEwJ6tF9x5WCIZDYzyZGaz6Khbw7raYRIBV_WxVvgmsG"
Token_type string // "Bearer"
App_id string // "APP-6XR95014BA15863X"
Expires_in int // 28800
}

Expand All @@ -37,7 +38,7 @@ type (

PaymentAmount struct {
Total string `json:"total"` // "3.20"
Currency string `json:"currency"` // EUR/USD/...
Currency string `json:"currency"` // EUR, USD, etc
Details PaymentAmountDetails `json:"details"`
}

Expand All @@ -62,15 +63,15 @@ type (
// --- PAYMENT RESPONSE ---

PaymentLink struct {
Href string `json:"href"` // "https://api.sandbox.paypal.com/v1/payments/payment/PAY-6RV70583SB702805EKEYSZ6Y",
Rel string `json:"rel"` // "self",
Href string `json:"href"` // "https://api.sandbox.paypal.com/v1/payments/payment/PAY-6RV70583SB702805EKEYSZ6Y"
Rel string `json:"rel"` // "self"
Method string `json:"method"` // "GET"
}

PaymentResponse struct {
Id string // "PAY-6RV70583SB702805EKEYSZ6Y",
CreateTime time.Time `json:"create_time` // 2013-03-01T22:34:35Z",
UpdateTime time.Time `json:"update_time"` // 2013-03-01T22:34:36Z",
Id string // "PAY-6RV70583SB702805EKEYSZ6Y"
CreateTime time.Time `json:"create_time` // 2013-03-01T22:34:35Z"
UpdateTime time.Time `json:"update_time"` // 2013-03-01T22:34:36Z"
State string // created
Intent string // sale
Payer PaymentPayer
Expand All @@ -84,9 +85,9 @@ type (
}

LookupSaleResponse struct {
Id string // "36C38912MN9658832",
CreateTime time.Time `json:"create_time` // 2013-03-01T22:34:35Z",
UpdateTime time.Time `json:"update_time"` // 2013-03-01T22:34:36Z",
Id string // "36C38912MN9658832"
CreateTime time.Time `json:"create_time` // 2013-03-01T22:34:35Z"
UpdateTime time.Time `json:"update_time"` // 2013-03-01T22:34:36Z"
State string // created
Amount PaymentAmount
ParentPayment string `json:"parent_payment"`
Expand Down Expand Up @@ -117,7 +118,7 @@ func GetToken(clientId string, secret string) (string, error) {
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(clientId, secret)

fmt.Print("Request absetzen...")
fmt.Print("Complete request...")
client := new(http.Client)
res, err := client.Do(req)
if err != nil {
Expand Down Expand Up @@ -146,8 +147,7 @@ func CreatePayPalPayment(

total := subtotal + tax + shipping

// Request zusammenbauen.

// Assemble Request
preq := PaymentRequest{
Intent: "sale",
RedirectUrls: PaymentUrls{
Expand All @@ -173,8 +173,8 @@ func CreatePayPalPayment(
},
}

// Http-Request zusammenbauen.
fmt.Print("Request erstellen...")
// Assemble Http-Request
fmt.Print("Create request...")
data, err := json.Marshal(preq)
if err != nil {
return nil, err
Expand All @@ -193,21 +193,21 @@ func CreatePayPalPayment(
req.Header.Add("Accept", "*/*")
req.Header.Add("Authorization", "Bearer "+token)

fmt.Print("Request absetzen...")
fmt.Print("Complete request...")
client := new(http.Client)
res, err := client.Do(req)
if err != nil {
return nil, err
}

// Http.Response einlesen.
// Read in Http.Response
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}

// Http-Response parsen.
// Parse Http-Response
if res.StatusCode == 201 {
ppres := &PaymentResponse{}
err = json.Unmarshal(body, &ppres)
Expand All @@ -220,7 +220,7 @@ func CreatePayPalPayment(
return nil, errors.New(fmt.Sprintf("%s: %s", res.Status, body))
}

// Macht aus einer authorisierten Bezahlung einen Verkauf.
// Create a purchase from an authorized payment
func ExecuteApprovedPayment(token string, payerId string, paymentId string) (*PaymentResponse, error) {
url := fmt.Sprintf("https://api.sandbox.paypal.com/v1/payments/payment/%s/execute", paymentId)
body := strings.NewReader("{ \"payer_id\": \"" + payerId + "\" }")
Expand Down Expand Up @@ -251,7 +251,7 @@ func ExecuteApprovedPayment(token string, payerId string, paymentId string) (*Pa
return nil, errors.New(res.Status)
}

// Liefert die Details zu einer abgeschlossenen Bezahlung.
// Provides the detauls of a successful payment
func LookupSale(token string, transactionId string) (*LookupSaleResponse, error) {
url := fmt.Sprintf("https://api.sandbox.paypal.com/v1/payments/sale/%s", transactionId)
req, err := http.NewRequest("GET", url, nil)
Expand Down Expand Up @@ -281,7 +281,7 @@ func LookupSale(token string, transactionId string) (*LookupSaleResponse, error)
return nil, errors.New(res.Status)
}

// Wandelt einen float64 in einen String um, wie Paypal ihn braucht.
// Cast float64 to String for PayPal usage
func toPayPalPrice(amount float64) string {
return fmt.Sprintf("%.2f", amount)
}
Expand All @@ -291,11 +291,24 @@ func fetchEnvVars() (clientId, secret string) {
clientId = os.Getenv("PAYPAL_TEST_CLIENTID")

if len(clientId) <= 0 {
fmt.Errorf("Für den Test muss die ENV-Variable PAYPAL_TEST_CLIENTID gesetzt sein!")
fmt.Errorf("For testing you must first set your PAYPAL_TEST_CLIENTID ENV variable!")
}
secret = os.Getenv("PAYPAL_TEST_SECRET")
if len(secret) <= 0 {
fmt.Errorf("For testing you must first set your PAYPAL_TEST_SECRET ENV variable!")
}
return
}

func fetchEnvVarsParam(t *testing.T) (clientId, secret string) {
clientId = os.Getenv("PAYPAL_TEST_CLIENTID")

if len(clientId) <= 0 {
fmt.Errorf("For testing you must first set your PAYPAL_TEST_CLIENTID ENV variable!")
}
secret = os.Getenv("PAYPAL_TEST_SECRET")
if len(secret) <= 0 {
fmt.Errorf("Für den Test muss die ENV-Variable PAYPAL_TEST_SECRET gesetzt sein!")
fmt.Errorf("For testing you must first set your PAYPAL_TEST_SECRET ENV variable!")
}
return
}
Expand All @@ -320,45 +333,45 @@ func main() {
payment, err = CreatePayPalPayment(
token,
1.00, 0.20, 2.00, "USD",
"Die Dinge die ich eingekauft habe.",
"http://109.74.200.123:3000/ok", "http://109.74.200.123:3000/cancel")
"The products that I have purchased:",
"http://localhost:3000/ok", "http://localhost:3000/cancel")
if err != nil {
panic(err)
}
// Weiter zu PayPal.
// Redirect to PayPal.
url, err := payment.ApprovalUrl()
if err != nil {
panic(err)
}
http.Redirect(res, req, url, http.StatusFound)
})
m.Get("/cancel", func() string { return "Bezahlung abgebrochen" })
m.Get("/cancel", func() string { return "Payment cancelled" })
m.Get("/ok", func(res http.ResponseWriter, req *http.Request) string {
params := req.URL.Query()
// token := params["token"][0]
payerId := params["PayerID"][0]
// Bezahlung durchführen.
// Execute Payment
sale, err := ExecuteApprovedPayment(token, payerId, payment.Id)
if err != nil {
panic(err)
}

// if sale.State != "approved" {
// panic(errors.New(fmt.Sprintf("Zahlung ist nicht genehmigt!(%s)", sale.State)))
// panic(errors.New(fmt.Sprintf("Payment is not approved! (%s)", sale.State)))
// }

// Bezahlung überprüfen.
// Verify payment
sr, err := LookupSale(token, sale.RelatedResources[0].Sale.Id)
if err != nil {
panic(err)
}

if sr.State != "completed" {
panic(errors.New(fmt.Sprintf("Zahlung ist nicht genehmigt! (%s)", sr.State)))
panic(errors.New(fmt.Sprintf("Payment is not approved! (%s)", sr.State)))
}

// TODO: Überprüfen, ob das Geld auch wirklich überwiesen wurde.
return "Bezahlt!"
// TODO: Verify that the money has actually been transferred successfully.
return "Money transferred successfully!"
})

m.Run()
Expand Down
14 changes: 7 additions & 7 deletions pp_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package main provides ...

package main

import (
Expand All @@ -9,27 +9,27 @@ import (

func TestSpec(t *testing.T) {
Convey("Given some paypal credentials (ENV)", t, func() {
clientId, secret := fetchEnvVars(t)
clientId, secret := fetchEnvVarsParam(t)
var err error
var token string
var payment *PaymentResponse

Convey("When I request a token", func() {
Convey("When I request a token...", func() {
token, err = GetToken(clientId, secret)

Convey("Then I should get a access-token", func() {
Convey("then I should get an access-token", func() {
So(token, ShouldNotBeNil)
So(err, ShouldBeNil)
})

Convey("And I request a simple payment", func() {
Convey("When I request a simple payment...", func() {
payment, err = CreatePayPalPayment(
token,
1.00, 0.20, 2.00, "USD",
"Die Dinge die ich eingekauft habe.",
"The products that I have purchased:",
"http://lillypark.com/ok", "http://lillypark.com/cancel")

Convey("Then I should get a created payment ready for authorization", func() {
Convey("then I should get a created payment which is ready for authorization", func() {
So(err, ShouldBeNil)
So(payment, ShouldNotBeNil)

Expand Down
3 changes: 2 additions & 1 deletion run.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export PAYPAL_TEST_CLIENTID=AVPTXhAJxfjAZ8_cnGuNyu_aMe4B2qdZCCuUL29s-9RDZ2EBfJ-_ZRumVlKf
export PAYPAL_TEST_SECRET=EBdYXBBm79-louDdnYapeUjtV2U14Xj0ZudsYcKlNaVNxmnSBZLGlYzNSrIy
go run pp.go
go test
cmd /k
4 changes: 4 additions & 0 deletions run_main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export PAYPAL_TEST_CLIENTID=AVPTXhAJxfjAZ8_cnGuNyu_aMe4B2qdZCCuUL29s-9RDZ2EBfJ-_ZRumVlKf
export PAYPAL_TEST_SECRET=EBdYXBBm79-louDdnYapeUjtV2U14Xj0ZudsYcKlNaVNxmnSBZLGlYzNSrIy
go run pp.go
cmd /k
4 changes: 4 additions & 0 deletions run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export PAYPAL_TEST_CLIENTID=AVPTXhAJxfjAZ8_cnGuNyu_aMe4B2qdZCCuUL29s-9RDZ2EBfJ-_ZRumVlKf
export PAYPAL_TEST_SECRET=EBdYXBBm79-louDdnYapeUjtV2U14Xj0ZudsYcKlNaVNxmnSBZLGlYzNSrIy
go test
cmd /k