+2
-3
cmd/app/main.go
+2
-3
cmd/app/main.go
···
24
24
25
25
logger, _ := zap.NewDevelopment()
26
26
defer logger.Sync()
27
-
sugar := logger.Sugar()
28
27
29
28
providers := providers.NewUseProviders([]providers.Provider{
30
29
providers.NewBraintreeProvider(getEnv("BRAINTREE_URL", "http://localhost:8001")),
31
30
providers.NewStripeProvider(getEnv("STRIPE_URL", "http://localhost:8002")),
32
-
}, sugar)
31
+
}, logger)
33
32
paymentsService := service.NewPaymentService(providers)
34
33
35
34
port := getEnv("PORT", "8000")
36
-
server := web.NewServer(paymentsService, port, sugar)
35
+
server := web.NewServer(paymentsService, port, logger)
37
36
server.ConfigureRouter()
38
37
39
38
srvErr := make(chan error, 1)
+10
-10
internal/providers/provider.go
+10
-10
internal/providers/provider.go
···
9
9
"go.uber.org/zap"
10
10
)
11
11
12
-
var thirtySecondTimout = 30 * time.Second
12
+
var thirtySecondTimout = 5 * time.Second
13
13
14
14
type Provider interface {
15
15
GetName() string
···
19
19
type UseProviders struct {
20
20
providers []Provider
21
21
timeout time.Duration
22
-
logger *zap.SugaredLogger
22
+
logger *zap.Logger
23
23
}
24
24
25
-
func NewUseProviders(providers []Provider, logger *zap.SugaredLogger) *UseProviders {
25
+
func NewUseProviders(providers []Provider, logger *zap.Logger) *UseProviders {
26
26
return ConfigurableUseProvider(providers, logger, thirtySecondTimout)
27
27
}
28
28
29
-
func ConfigurableUseProvider(providers []Provider, logger *zap.SugaredLogger, timeout time.Duration) *UseProviders {
29
+
func ConfigurableUseProvider(providers []Provider, logger *zap.Logger, timeout time.Duration) *UseProviders {
30
30
return &UseProviders{
31
31
providers: providers,
32
32
logger: logger,
···
41
41
for _, provider := range p.providers {
42
42
select {
43
43
case data := <-p.charge(ctx, payment, provider):
44
-
p.logger.Debugw("[Payment] Sending request successfully",
45
-
"provider", provider.GetName(),
46
-
"attempt", attempts)
44
+
p.logger.Debug("[Payment] Received request successfully",
45
+
zap.String("provider", provider.GetName()),
46
+
zap.Int("attempt", attempts))
47
47
48
48
return data, nil
49
49
case <-time.After(p.timeout):
50
-
p.logger.Errorw("[Payment] Timeout for provider to respond",
51
-
"provider", provider.GetName(),
52
-
"attempt", attempts)
50
+
p.logger.Error("[Payment] Timeout for provider to respond",
51
+
zap.String("provider", provider.GetName()),
52
+
zap.Int("attempt", attempts))
53
53
54
54
err = errors.New("Timeout")
55
55
continue
+3
-6
internal/providers/provider_test.go
+3
-6
internal/providers/provider_test.go
···
31
31
t.Run("should make request for first provider", func(t *testing.T) {
32
32
logger, _ := zap.NewDevelopment()
33
33
defer logger.Sync()
34
-
sugar := logger.Sugar()
35
34
36
35
spyFirst := &SpyProvider{Timeout: 10 * time.Millisecond, Response: &domain.Provider{Description: "First"}}
37
36
spySecond := &SpyProvider{Timeout: 10 * time.Millisecond, Response: &domain.Provider{Description: "Second"}}
38
37
39
38
payment, _ := domain.NewPayment(1000, "R$", "", "card", domain.PaymentCard{Number: "", HolderName: "", CVV: "", ExpirationDate: "02/2025", Installments: 1})
40
39
41
-
useProvider := providers.ConfigurableUseProvider([]providers.Provider{spyFirst, spySecond}, sugar, 15*time.Millisecond)
40
+
useProvider := providers.ConfigurableUseProvider([]providers.Provider{spyFirst, spySecond}, logger, 15*time.Millisecond)
42
41
data, err := useProvider.Payment(context.Background(), payment)
43
42
44
43
if err != nil {
···
56
55
t.Run("should make request for second provider when first provider timeouts", func(t *testing.T) {
57
56
logger, _ := zap.NewProduction()
58
57
defer logger.Sync()
59
-
sugar := logger.Sugar()
60
58
61
59
spyFirst := &SpyProvider{Timeout: 20 * time.Millisecond, Response: &domain.Provider{Description: "First"}}
62
60
spySecond := &SpyProvider{Timeout: 10 * time.Millisecond, Response: &domain.Provider{Description: "Second"}}
63
61
64
62
payment, _ := domain.NewPayment(1000, "R$", "", "card", domain.PaymentCard{Number: "", HolderName: "", CVV: "", ExpirationDate: "02/2025", Installments: 1})
65
63
66
-
useProvider := providers.ConfigurableUseProvider([]providers.Provider{spyFirst, spySecond}, sugar, 15*time.Millisecond)
64
+
useProvider := providers.ConfigurableUseProvider([]providers.Provider{spyFirst, spySecond}, logger, 15*time.Millisecond)
67
65
data, err := useProvider.Payment(context.Background(), payment)
68
66
69
67
if err != nil {
···
81
79
t.Run("should return error when all providers timeout", func(t *testing.T) {
82
80
logger, _ := zap.NewProduction()
83
81
defer logger.Sync()
84
-
sugar := logger.Sugar()
85
82
86
83
spyFirst := &SpyProvider{Timeout: 20 * time.Millisecond, Response: &domain.Provider{Description: "First"}}
87
84
spySecond := &SpyProvider{Timeout: 20 * time.Millisecond, Response: &domain.Provider{Description: "Second"}}
88
85
89
86
payment, _ := domain.NewPayment(1000, "R$", "", "card", domain.PaymentCard{Number: "", HolderName: "", CVV: "", ExpirationDate: "02/2025", Installments: 1})
90
87
91
-
useProvider := providers.ConfigurableUseProvider([]providers.Provider{spyFirst, spySecond}, sugar, 5*time.Millisecond)
88
+
useProvider := providers.ConfigurableUseProvider([]providers.Provider{spyFirst, spySecond}, logger, 5*time.Millisecond)
92
89
data, err := useProvider.Payment(context.Background(), payment)
93
90
94
91
if data != nil {
+1
-4
internal/service/payment_service.go
+1
-4
internal/service/payment_service.go
···
2
2
3
3
import (
4
4
"context"
5
-
"fmt"
6
5
7
6
"github.com/Tulkdan/payment-gateway/internal/domain"
8
7
"github.com/Tulkdan/payment-gateway/internal/dto"
···
23
22
return nil, err
24
23
}
25
24
26
-
data, err := p.providers.Payment(ctx, payment)
25
+
_, err = p.providers.Payment(ctx, payment)
27
26
if err != nil {
28
27
return nil, err
29
28
}
30
-
31
-
fmt.Println(data)
32
29
33
30
return &dto.PaymentOutput{Message: "Processed successfully"}, nil
34
31
}
+12
-8
internal/web/handler/payments_handler.go
+12
-8
internal/web/handler/payments_handler.go
···
12
12
type PaymentsHandler struct {
13
13
paymentService *service.PaymentService
14
14
15
-
logger *zap.SugaredLogger
15
+
logger *zap.Logger
16
16
}
17
17
18
-
func NewPaymentsHandler(paymentsService *service.PaymentService, logger *zap.SugaredLogger) *PaymentsHandler {
18
+
func NewPaymentsHandler(paymentsService *service.PaymentService, logger *zap.Logger) *PaymentsHandler {
19
19
return &PaymentsHandler{
20
20
paymentService: paymentsService,
21
21
logger: logger.Named("PaymentHandler"),
···
25
25
func (p *PaymentsHandler) Create(w http.ResponseWriter, r *http.Request) {
26
26
var body dto.PaymentInput
27
27
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
28
-
p.logger.Errorw("Body incomplete",
29
-
"error", err.Error(),
30
-
"requestId", r.Context().Value("request-id").(string))
28
+
p.logger.Error("Body incomplete",
29
+
zap.String("error", err.Error()),
30
+
zap.String("requestId", r.Context().Value("request-id").(string)))
31
31
32
32
http.Error(w, err.Error(), http.StatusBadRequest)
33
33
return
···
35
35
36
36
response, err := p.paymentService.CreatePayment(r.Context(), body)
37
37
if err != nil {
38
-
p.logger.Errorw("Failed to create payment",
39
-
"error", err.Error(),
40
-
"requestId", r.Context().Value("request-id").(string))
38
+
p.logger.Error("Failed to create payment",
39
+
zap.String("error", err.Error()),
40
+
zap.String("requestId", r.Context().Value("request-id").(string)))
41
41
42
42
http.Error(w, err.Error(), http.StatusBadRequest)
43
43
return
44
44
}
45
+
46
+
p.logger.Debug("Processed request",
47
+
zap.Any("response", response),
48
+
zap.String("requestId", r.Context().Value("request-id").(string)))
45
49
46
50
w.Header().Set("Content-Type", "application/json")
47
51
w.WriteHeader(http.StatusOK)
+2
-2
internal/web/server.go
+2
-2
internal/web/server.go
···
16
16
port string
17
17
router *http.ServeMux
18
18
server *http.Server
19
-
logger *zap.SugaredLogger
19
+
logger *zap.Logger
20
20
21
21
paymentsService *service.PaymentService
22
22
}
23
23
24
-
func NewServer(paymentsService *service.PaymentService, port string, logger *zap.SugaredLogger) *Server {
24
+
func NewServer(paymentsService *service.PaymentService, port string, logger *zap.Logger) *Server {
25
25
return &Server{
26
26
port: port,
27
27
paymentsService: paymentsService,
+1
-1
mocks/braintree.yml
+1
-1
mocks/braintree.yml