-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
129 lines (113 loc) · 4.32 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package ctechpay
import (
"encoding/json"
"fmt"
"io"
"log/slog"
"math/big"
"net/http"
"net/url"
"time"
)
const ProductionURL = "https://api-sandbox.ctechpay.com/"
const SandboxURL = "https://api-sandbox.ctechpay.com/"
const defaultCancelText = "Cancel Payment"
// Client is the client type for interacting with the CTechPay API
type Client struct {
APIToken string
BaseURL string
httpClient *http.Client
redirectURL string
cancelURL string
cancelText string
Logger *slog.Logger
}
// OrderRequest initiates an order request
type OrderRequest struct {
Token string `json:"token" form:"token"`
Amount big.Float `json:"amount" form:"amount"`
MerchantAttributes bool `json:"merchantAttributes,omitempty" form:"merchantAttributes"` // Merchant attributes enable you to include your custom options when the customer is interacting with the payment page. Set to true to enable the following compulsory and optional parameters: (redirectUrl, cancelUrl, cancelText) true
RedirectUrl string `json:"redirectUrl,omitempty" form:"redirectUrl"` // A compulsory URL to redirect the user after a payment has been made. https://example.com/ Note: Only https requests are supported
CancelUrl string `json:"cancelUrl,omitempty" form:"cancelUrl"` // A compulsory URL to redirect the user when they choose to cancel the payment. https://example.com/ Note: Only https requests are supported
CancelText string `json:"cancelText,omitempty" form:"cancelText"` // An optional custom text on the cancelUrl link “Go back to shop,” “Cancel Payment”
}
// OrderResponse contains information about order response from CTechPay
type OrderResponse struct {
TxnID string `json:"-"`
OrderReference string `json:"order_reference"`
PaymentPageURL string `json:"payment_page_URL"`
}
// NewClient creates a new Production client for CTechPay
func NewClient(token string, timeout time.Duration) *Client {
return &Client{
APIToken: token,
BaseURL: ProductionURL,
httpClient: &http.Client{
Timeout: timeout,
},
Logger: slog.Default(),
}
}
// NewSandboxClient creates a new Sandbox/Testing client for CTechPay
func NewSandboxClient(token string, timeout time.Duration) *Client {
return &Client{
APIToken: token,
BaseURL: SandboxURL,
httpClient: &http.Client{
Timeout: timeout,
},
Logger: slog.Default(),
}
}
// SetRedirectURL sets the redirect url for subsequent order requests
func (c *Client) SetRedirectURL(redirectURL string) {
c.redirectURL = redirectURL
}
// SetCancelURL sets the cancel url and cancel text for subsequent order requests. cancel text defaults to "Cancel Payment"
func (c *Client) SetCancelURL(cancelURL, cancelText string) {
c.cancelURL = cancelURL
if cancelText != "" {
c.cancelText = cancelText
} else {
c.cancelText = defaultCancelText
}
}
// InitiateCardOrder initiates a payment transaction that will be fulfilled on the CTechPay platform
func (c *Client) InitiateCardOrder(txnID string, amount big.Float, merchant bool) (*OrderResponse, error) {
form := url.Values{}
form.Set("token", c.APIToken)
form.Set("amount", amount.String())
if merchant {
if c.redirectURL == "" {
return nil, fmt.Errorf("redirectURL must be set via *Client.SetRedirectURL(string)")
}
if c.cancelURL == "" {
return nil, fmt.Errorf("cancelURL must be set via *Client.SetCancelURL(string, string)")
}
if c.cancelText == "" {
return nil, fmt.Errorf("cancelText must be set via *Client.SetCancelURL(string, string)")
}
form.Set("merchantAttributes", "true")
form.Set("redirectUrl", c.redirectURL)
form.Set("cancelUrl", c.cancelURL)
form.Set("cancelText", c.cancelText)
}
url := fmt.Sprintf("%s/?endpoint=order", c.BaseURL)
c.Logger.Debug("Sending request to CTechPay at", "url", url)
resp, err := c.httpClient.PostForm(url, form)
if err != nil {
return nil, fmt.Errorf("failed to create order, got: %w", err)
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body, got: %w", err)
}
var orderResponse OrderResponse
err = json.Unmarshal(data, &orderResponse)
if err != nil {
return nil, fmt.Errorf("failed to parse order response as JSON %w", err)
}
orderResponse.TxnID = txnID
return &orderResponse, nil
}