Skip to content
24 changes: 10 additions & 14 deletions cmd/events_resend.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,14 @@ func resendEvent(id string) error {
return fmt.Errorf("event %s found but has no raw payload stored", id)
}

defaultURL := "http://localhost:3000/webhooks/abacatepay"
if resendForwardURL == "" {
if entry.URL != "" {
defaultURL = entry.URL
}

if inputErr := style.Input("Forward event to", defaultURL, &resendForwardURL, nil); inputErr != nil {
return inputErr
}
if resendForwardURL == "" {
resendForwardURL = defaultURL
}
defaultURL := utils.DefaultForwardURL
if entry.URL != "" {
defaultURL = entry.URL
}

url, err := utils.GetForwardURL(resendForwardURL, defaultURL)
if err != nil {
return err
}

deps := utils.SetupDependencies(Local, Verbose)
Expand All @@ -60,14 +56,14 @@ func resendEvent(id string) error {
signature := crypto.SignWebhookPayload(secret, timestamp, []byte(entry.RawMessage))

style.LogSigningSecret(secret)
fmt.Printf("Resending event %s to %s...\n", id, resendForwardURL)
fmt.Printf("Resending event %s to %s...\n", id, url)

startTime := time.Now()
resp, err := deps.Client.R().
SetHeader("Content-Type", "application/json").
SetHeader("X-Abacate-Signature", fmt.Sprintf("t=%d,v1=%s", timestamp, signature)).
SetBody(entry.RawMessage).
Post(resendForwardURL)
Post(url)

duration := time.Since(startTime)

Expand Down
17 changes: 4 additions & 13 deletions cmd/listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"os/signal"
"syscall"

"abacatepay-cli/internal/style"
"abacatepay-cli/internal/utils"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -38,27 +37,19 @@ func listen(cmd *cobra.Command) error {
return err
}

defaultURL := "http://localhost:3000/webhooks/abacatepay"
if !cmd.Flags().Changed("forward-to") {
err := style.Input("Forward events to", defaultURL, &forwardURL, nil)
if err != nil {
return err
}

if forwardURL == "" {
forwardURL = defaultURL
}
url, err := utils.GetForwardURL(forwardURL, utils.DefaultForwardURL)
if err != nil {
return err
}

ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)

defer cancel()

params := &utils.StartListenerParams{
Context: ctx,
Config: deps.Config,
Client: deps.Client,
ForwardURL: forwardURL,
ForwardURL: url,
Store: deps.Store,
Token: deps.Config.TokenKey,
Version: cmd.Root().Version,
Expand Down
12 changes: 3 additions & 9 deletions cmd/payments_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cmd

import (
"abacatepay-cli/internal/payments"
"abacatepay-cli/internal/utils"

"github.com/spf13/cobra"
)
Expand All @@ -21,12 +20,7 @@ func init() {
}

func check(paymentID string) error {
deps, err := utils.SetupClient(Local, Verbose)
if err != nil {
return err
}

pixService := payments.New(deps.Client, deps.Config.APIBaseURL)

return pixService.CheckPixQRCode(paymentID)
return payments.ExecutePaymentAction(Local, Verbose, func(s *payments.Service) error {
return s.CheckPixQRCode(paymentID)
})
}
2 changes: 1 addition & 1 deletion cmd/payments_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func createPayment(method string) error {
}
}

service := payments.New(deps.Client, deps.Config.APIBaseURL)
service := payments.New(deps.Client, deps.Config.APIBaseURL, Verbose)

switch method {
case "pix", "pix_qrcode":
Expand Down
12 changes: 3 additions & 9 deletions cmd/payments_simulate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cmd

import (
"abacatepay-cli/internal/payments"
"abacatepay-cli/internal/utils"

"github.com/spf13/cobra"
)
Expand All @@ -21,12 +20,7 @@ func init() {
}

func simulate(paymentID string) error {
deps, err := utils.SetupClient(Local, Verbose)
if err != nil {
return err
}

pixService := payments.New(deps.Client, deps.Config.APIBaseURL)

return pixService.SimulatePixQRCodePayment(paymentID, false)
return payments.ExecutePaymentAction(Local, Verbose, func(s *payments.Service) error {
return s.SimulatePixQRCodePayment(paymentID, false)
})
}
2 changes: 1 addition & 1 deletion cmd/trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func trigger(evt string) error {
}

func handleEvent(deps *utils.Dependencies, evt string) error {
service := payments.New(deps.Client, deps.Config.APIBaseURL)
service := payments.New(deps.Client, deps.Config.APIBaseURL, Verbose)

switch evt {
case "billing.paid":
Expand Down
7 changes: 4 additions & 3 deletions internal/auth/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ type LoginParams struct {
}

func Login(params *LoginParams) error {
if params.ProfileName == "" {
params.ProfileName = fmt.Sprintf("profile-%d", time.Now().Unix()%10000)
if params.APIKey != "" {
return loginWithAPIKey(params)
}

if params.APIKey != "" {
if params.Config.APIBaseURL == "http://191.252.202.128:8080" {
params.APIKey = "mock_token_local_dev"
return loginWithAPIKey(params)
}

Expand Down
3 changes: 1 addition & 2 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ import (
func New(cfg *config.Config) *resty.Client {
return resty.New().
SetTimeout(cfg.HTTPTimeout).
SetHeader("User-Agent", "abacatepay-cli/1.0").
SetDebug(cfg.Verbose)
SetHeader("User-Agent", "abacatepay-cli/1.0")
}
2 changes: 1 addition & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func Default() *Config {
WebSocketBaseURL: "wss://ws.abacatepay.com/ws",
ServiceName: "abacatepay-cli",
TokenKey: "auth-token",
HTTPTimeout: 10 * time.Second,
HTTPTimeout: 15 * time.Second,
DefaultForwardURL: "http://localhost:3000/webhooks",
Verbose: false,
}
Expand Down
29 changes: 7 additions & 22 deletions internal/output/output.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package output

import (
"encoding/json"
"fmt"
"log/slog"
"os"
"sync"

"abacatepay-cli/internal/style"
Expand Down Expand Up @@ -110,19 +107,11 @@ func printJSON(r Result) {
}
}

encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
if err := encoder.Encode(data); err != nil {
slog.Debug("failed to encode JSON output", "error", err)
}
style.PrintJSON(data)
}

func printJSONError(msg string) {
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
if err := encoder.Encode(map[string]any{"error": msg}); err != nil {
slog.Debug("failed to encode JSON error output", "error", err)
}
style.PrintJSON(map[string]any{"error": msg})
}

func printText(r Result) {
Expand Down Expand Up @@ -165,19 +154,15 @@ func printProfilesJSON(profiles []Profile, activeProfile string) {
profileData := make([]map[string]any, 0, len(profiles))
for _, p := range profiles {
profileData = append(profileData, map[string]any{
"name": p.Name,
"active": p.Active,
"name": p.Name,
"key": formatShortToken(p.Token),
})
}

encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
if err := encoder.Encode(map[string]any{
style.PrintJSON(map[string]any{
"profiles": profileData,
"active": activeProfile,
}); err != nil {
slog.Debug("failed to encode profiles JSON output", "error", err)
}
})
}

func printProfilesTable(profiles []Profile) {
Expand All @@ -187,7 +172,7 @@ func printProfilesTable(profiles []Profile) {
shortKey := formatShortToken(p.Token)
activeMarker := ""
if p.Active {
activeMarker = "Yes"
activeMarker = "🥑"
}
rows = append(rows, []string{p.Name, shortKey, activeMarker})
}
Expand Down
31 changes: 30 additions & 1 deletion internal/payments/payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"

"abacatepay-cli/internal/output"
"abacatepay-cli/internal/style"
"abacatepay-cli/internal/types"

"github.com/go-resty/resty/v2"
Expand All @@ -14,16 +15,35 @@ import (
type Service struct {
Client *resty.Client
BaseURL string
Verbose bool
}

func New(client *resty.Client, baseURL string) *Service {
func New(client *resty.Client, baseURL string, verbose bool) *Service {
return &Service{
Client: client,
BaseURL: baseURL,
Verbose: verbose,
}
}

func (s *Service) executeRequest(req *resty.Request, method, url string, result any) error {
if s.Verbose {
fmt.Printf("Request: %s %s\n", method, url)
if body := req.Body; body != nil {
if b, ok := body.([]byte); ok {
var pretty any
if err := json.Unmarshal(b, &pretty); err == nil {
style.PrintJSON(pretty)
} else {
fmt.Println(string(b))
}
} else {
style.PrintJSON(body)
}
}
fmt.Println()
}

var resp *resty.Response
var err error

Expand All @@ -40,6 +60,10 @@ func (s *Service) executeRequest(req *resty.Request, method, url string, result
return fmt.Errorf("failed to send request: %w", err)
}

if s.Verbose {
fmt.Printf("Response: %s\n", resp.Status())
}

if resp.IsError() {
return s.handleAPIError(resp)
}
Expand All @@ -48,6 +72,11 @@ func (s *Service) executeRequest(req *resty.Request, method, url string, result
return fmt.Errorf("failed to parse response: %w", err)
}

if s.Verbose {
style.PrintJSON(result)
fmt.Println()
}

return nil
}

Expand Down
13 changes: 13 additions & 0 deletions internal/payments/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package payments

import "abacatepay-cli/internal/utils"

func ExecutePaymentAction(local, verbose bool, action func(*Service) error) error {
deps, err := utils.SetupClient(local, verbose)
if err != nil {
return err
}

pixService := New(deps.Client, deps.Config.APIBaseURL, verbose)
return action(pixService)
}
1 change: 0 additions & 1 deletion internal/style/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ func PrintTable(headers []string, rows [][]string) {
t.StyleFunc(func(row, col int) lipgloss.Style {
if row == 0 {
return lipgloss.NewStyle().
Foreground(Palette.Green).
Bold(true).
Align(lipgloss.Center)
}
Expand Down
44 changes: 44 additions & 0 deletions internal/utils/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,55 @@ package utils
import (
"fmt"
"net"
"net/url"
"os/exec"
"runtime"
"time"

"abacatepay-cli/internal/style"
)

const DefaultForwardURL = "http://localhost:3000/webhooks/abacatepay"

func validateForwardURL(s string) error {
u, err := url.ParseRequestURI(s)
if err != nil {
return fmt.Errorf("invalid URL format: %w", err)
}
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("URL must start with http:// or https://")
}
if u.Host == "" {
return fmt.Errorf("URL must include a valid host")
}
return nil
}

func promptForwardURL(defaultURL string, result *string) error {
if err := style.Input("Forward events to", defaultURL, result, validateForwardURL); err != nil {
return err
}
if *result == "" {
*result = defaultURL
}
return nil
}

func GetForwardURL(flagValue, defaultURL string) (string, error) {
if flagValue != "" {
if err := validateForwardURL(flagValue); err != nil {
return "", err
}
return flagValue, nil
}

var result string
if err := promptForwardURL(defaultURL, &result); err != nil {
return "", err
}
return result, nil
}

func IsOnline() bool {
const googleDNS = "8.8.8.8:53"
const timeout = 2 * time.Second
Expand Down