add context

This commit is contained in:
Cyrill Schumacher 2021-03-05 14:38:22 +01:00
parent 415a8f7f76
commit 3e4652d535
2 changed files with 37 additions and 35 deletions

View File

@ -2,6 +2,7 @@ package datatrans
import (
"bytes"
"context"
"crypto/tls"
"encoding/hex"
"encoding/json"
@ -191,7 +192,7 @@ func MarshalJSON(postData interface{}) ([]byte, error) {
return jsonBytes, nil
}
func (c *Client) prepareJSONReq(method, path string, postData interface{}) (*http.Request, error) {
func (c *Client) prepareJSONReq(ctx context.Context, method, path string, postData interface{}) (*http.Request, error) {
internalID := c.currentInternalID
var r io.Reader
@ -209,7 +210,7 @@ func (c *Client) prepareJSONReq(method, path string, postData interface{}) (*htt
host = endpointURLProduction
}
req, err := http.NewRequest(method, host+path, r)
req, err := http.NewRequestWithContext(ctx, method, host+path, r)
if err != nil {
return nil, fmt.Errorf("ClientID:%q: failed to create HTTP request: %w", internalID, err)
}
@ -230,7 +231,7 @@ func (c *Client) prepareJSONReq(method, path string, postData interface{}) (*htt
// Status allows once a transactionId has been received the status can be checked
// with the Status API.
func (c *Client) Status(transactionID string) (*ResponseStatus, error) {
func (c *Client) Status(ctx context.Context, transactionID string) (*ResponseStatus, error) {
if transactionID == "" {
return nil, fmt.Errorf("transactionID cannot be empty")
}
@ -239,7 +240,7 @@ func (c *Client) Status(transactionID string) (*ResponseStatus, error) {
if c.merchants[internalID].EnableProduction {
host = endpointURLProduction
}
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(host+pathStatus, transactionID), nil)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf(host+pathStatus, transactionID), nil)
if err != nil {
return nil, fmt.Errorf("ClientID:%q: failed to create HTTP request: %w", internalID, err)
}
@ -254,12 +255,12 @@ func (c *Client) Status(transactionID string) (*ResponseStatus, error) {
// Credit uses the credit API to credit a transaction which is in status settled.
// The previously settled amount must not be exceeded.
func (c *Client) Credit(transactionID string, rc RequestCredit) (*ResponseCardMasked, error) {
func (c *Client) Credit(ctx context.Context, transactionID string, rc RequestCredit) (*ResponseCardMasked, error) {
if transactionID == "" || rc.Currency == "" || rc.RefNo == "" {
return nil, fmt.Errorf("neither currency nor refno nor transactionID can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, fmt.Sprintf(pathCredit, transactionID), rc)
req, err := c.prepareJSONReq(ctx, http.MethodPost, fmt.Sprintf(pathCredit, transactionID), rc)
if err != nil {
return nil, err
}
@ -275,12 +276,12 @@ func (c *Client) Credit(transactionID string, rc RequestCredit) (*ResponseCardMa
// CreditAuthorize allows to use this API to make a credit without referring to a
// previous authorization. This can be useful if you want to credit a cardholder
// when there was no debit.
func (c *Client) CreditAuthorize(rca RequestCreditAuthorize) (*ResponseCardMasked, error) {
func (c *Client) CreditAuthorize(ctx context.Context, rca RequestCreditAuthorize) (*ResponseCardMasked, error) {
if rca.Currency == "" || rca.RefNo == "" || rca.Amount == 0 {
return nil, fmt.Errorf("neither currency nor refno nor amount can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, pathCreditAuthorize, rca)
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathCreditAuthorize, rca)
if err != nil {
return nil, err
}
@ -296,11 +297,11 @@ func (c *Client) CreditAuthorize(rca RequestCreditAuthorize) (*ResponseCardMaske
// The transaction must either be in status authorized or settled. The
// transactionId is needed to cancel an authorization.
// https://api-reference.datatrans.ch/#operation/cancel
func (c *Client) Cancel(transactionID string, refno string) error {
func (c *Client) Cancel(ctx context.Context, transactionID string, refno string) error {
if transactionID == "" || refno == "" {
return fmt.Errorf("neither transactionID nor refno can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, fmt.Sprintf(pathCancel, transactionID), struct {
req, err := c.prepareJSONReq(ctx, http.MethodPost, fmt.Sprintf(pathCancel, transactionID), struct {
Refno string `json:"refno"`
}{
Refno: refno,
@ -320,11 +321,11 @@ func (c *Client) Cancel(transactionID string, refno string) error {
// transactionId is needed to settle an authorization. Note: This API call is not
// needed if "autoSettle": true was used when initializing a transaction.
// https://api-reference.datatrans.ch/#operation/settle
func (c *Client) Settle(transactionID string, rs RequestSettle) error {
func (c *Client) Settle(ctx context.Context, transactionID string, rs RequestSettle) error {
if transactionID == "" || rs.Amount == 0 || rs.Currency == "" || rs.RefNo == "" {
return fmt.Errorf("neither transactionID nor refno nor amount nor currency can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, fmt.Sprintf(pathSettle, transactionID), rs)
req, err := c.prepareJSONReq(ctx, http.MethodPost, fmt.Sprintf(pathSettle, transactionID), rs)
if err != nil {
return err
}
@ -340,11 +341,11 @@ func (c *Client) Settle(transactionID string, rs RequestSettle) error {
// Only credit cards (including Apple Pay and Google Pay), PFC, KLN and PAP
// support validation of an existing alias.
// https://api-reference.datatrans.ch/#operation/validate
func (c *Client) ValidateAlias(rva RequestValidateAlias) (*ResponseCardMasked, error) {
func (c *Client) ValidateAlias(ctx context.Context, rva RequestValidateAlias) (*ResponseCardMasked, error) {
if rva.Currency == "" || rva.RefNo == "" {
return nil, fmt.Errorf("neither currency nor refno can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, pathValidate, rva)
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathValidate, rva)
if err != nil {
return nil, err
}
@ -360,11 +361,11 @@ func (c *Client) ValidateAlias(rva RequestValidateAlias) (*ResponseCardMasked, e
// transaction the parameter option.authenticationOnly was set to true, this API
// can be used to authorize an already authenticated (3D) transaction.
// https://api-reference.datatrans.ch/#operation/authorize-split
func (c *Client) AuthorizeTransaction(transactionID string, rva RequestAuthorizeTransaction) (*ResponseAuthorize, error) {
func (c *Client) AuthorizeTransaction(ctx context.Context, transactionID string, rva RequestAuthorizeTransaction) (*ResponseAuthorize, error) {
if transactionID == "" || rva.RefNo == "" {
return nil, fmt.Errorf("neither transactionID nor refno can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, fmt.Sprintf(pathAuthorizeTransaction, transactionID), rva)
req, err := c.prepareJSONReq(ctx, http.MethodPost, fmt.Sprintf(pathAuthorizeTransaction, transactionID), rva)
if err != nil {
return nil, err
}
@ -382,11 +383,11 @@ func (c *Client) AuthorizeTransaction(transactionID string, rva RequestAuthorize
// the payment method specific objects (for example PAP) to see which parameters
// so send. For credit cards, the card object can be used.
// https://api-reference.datatrans.ch/#operation/authorize
func (c *Client) Authorize(rva RequestAuthorize) (*ResponseCardMasked, error) {
func (c *Client) Authorize(ctx context.Context, rva RequestAuthorize) (*ResponseCardMasked, error) {
if rva.Amount == 0 || rva.Currency == "" || rva.RefNo == "" {
return nil, fmt.Errorf("neither transactionID nor amount nor currency nor refno can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, pathAuthorize, rva)
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathAuthorize, rva)
if err != nil {
return nil, err
}
@ -407,11 +408,11 @@ func (c *Client) Authorize(rva RequestAuthorize) (*ResponseCardMasked, error) {
// Datatrans Payment Page with all the payment methods available for the given
// merchantId. If you want to limit the number of payment methods, the
// paymentMethod array can be used.
func (c *Client) Initialize(rva RequestInitialize) (*ResponseInitialize, error) {
func (c *Client) Initialize(ctx context.Context, rva RequestInitialize) (*ResponseInitialize, error) {
if rva.Amount == 0 || rva.Currency == "" || rva.RefNo == "" {
return nil, fmt.Errorf("neither amount nor currency nor refno can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, pathInitialize, rva)
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathInitialize, rva)
if err != nil {
return nil, err
}
@ -426,11 +427,11 @@ func (c *Client) Initialize(rva RequestInitialize) (*ResponseInitialize, error)
// InitializeSecureFields initializes a Secure Fields transaction. Proceed with
// the steps below to process Secure Fields payment transactions.
// https://api-reference.datatrans.ch/#operation/secureFieldsInit
func (c *Client) SecureFieldsInit(rva RequestSecureFieldsInit) (*ResponseInitialize, error) {
func (c *Client) SecureFieldsInit(ctx context.Context, rva RequestSecureFieldsInit) (*ResponseInitialize, error) {
if rva.Amount == 0 || rva.Currency == "" || rva.ReturnUrl == "" {
return nil, fmt.Errorf("neither amount nor currency nor returnURL can be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, pathSecureFields, rva)
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathSecureFields, rva)
if err != nil {
return nil, err
}
@ -446,11 +447,11 @@ func (c *Client) SecureFieldsInit(rva RequestSecureFieldsInit) (*ResponseInitial
// transaction. This action is only allowed before the 3D process. At least one
// property must be updated.
// https://api-reference.datatrans.ch/#operation/secure-fields-update
func (c *Client) SecureFieldsUpdate(transactionID string, rva RequestSecureFieldsUpdate) error {
func (c *Client) SecureFieldsUpdate(ctx context.Context, transactionID string, rva RequestSecureFieldsUpdate) error {
if rva.Amount == 0 || rva.Currency == "" {
return fmt.Errorf("neither amount nor currency nor returnURL can be empty")
}
req, err := c.prepareJSONReq(http.MethodPatch, fmt.Sprintf(pathSecureFieldsUpdate, transactionID), rva)
req, err := c.prepareJSONReq(ctx, http.MethodPatch, fmt.Sprintf(pathSecureFieldsUpdate, transactionID), rva)
if err != nil {
return err
}
@ -463,11 +464,11 @@ func (c *Client) SecureFieldsUpdate(transactionID string, rva RequestSecureField
// AliasConvert converts a legacy (numeric or masked) alias to the most recent
// alias format.
func (c *Client) AliasConvert(legacyAlias string) (string, error) {
func (c *Client) AliasConvert(ctx context.Context, legacyAlias string) (string, error) {
if legacyAlias == "" {
return "", fmt.Errorf("legacyAlias cannot be empty")
}
req, err := c.prepareJSONReq(http.MethodPost, pathAliases, struct {
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathAliases, struct {
LegacyAlias string `json:"legacyAlias"`
}{
LegacyAlias: legacyAlias,
@ -486,11 +487,11 @@ func (c *Client) AliasConvert(legacyAlias string) (string, error) {
// AliasDelete deletes an alias with immediate effect. The alias will no longer
// be recognized if used later with any API call.
func (c *Client) AliasDelete(alias string) error {
func (c *Client) AliasDelete(ctx context.Context, alias string) error {
if alias == "" {
return fmt.Errorf("alias cannot be empty")
}
req, err := c.prepareJSONReq(http.MethodDelete, fmt.Sprintf(pathAliasesDelete, alias), nil)
req, err := c.prepareJSONReq(ctx, http.MethodDelete, fmt.Sprintf(pathAliasesDelete, alias), nil)
if err != nil {
return err
}
@ -502,8 +503,8 @@ func (c *Client) AliasDelete(alias string) error {
// ReconciliationsSales reports a sale. When using reconciliation, use this API
// to report a sale. The matching is based on the transactionId.
func (c *Client) ReconciliationsSales(sale RequestReconciliationsSale) (*ResponseReconciliationsSale, error) {
req, err := c.prepareJSONReq(http.MethodPost, pathReconciliationsSales, sale)
func (c *Client) ReconciliationsSales(ctx context.Context, sale RequestReconciliationsSale) (*ResponseReconciliationsSale, error) {
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathReconciliationsSales, sale)
if err != nil {
return nil, err
}
@ -517,8 +518,8 @@ func (c *Client) ReconciliationsSales(sale RequestReconciliationsSale) (*Respons
// ReconciliationsSalesBulk reports bulk sales. When using reconciliation, use
// this API to report multiples sales with a single API call. The matching is
// based on the transactionId.
func (c *Client) ReconciliationsSalesBulk(sales RequestReconciliationsSales) (*ResponseReconciliationsSales, error) {
req, err := c.prepareJSONReq(http.MethodPost, pathReconciliationsSalesBulk, sales)
func (c *Client) ReconciliationsSalesBulk(ctx context.Context, sales RequestReconciliationsSales) (*ResponseReconciliationsSales, error) {
req, err := c.prepareJSONReq(ctx, http.MethodPost, pathReconciliationsSalesBulk, sales)
if err != nil {
return nil, err
}

View File

@ -2,6 +2,7 @@ package datatrans_test
import (
"bytes"
"context"
"errors"
"io/ioutil"
"net/http"
@ -57,7 +58,7 @@ func TestClient_Status(t *testing.T) {
)
must(t, err)
rs, err := c.Status("3423423423")
rs, err := c.Status(context.Background(), "3423423423")
must(t, err)
if rs.TransactionID != "210215103042148501" {
t.Errorf("incorrect TransactionID:%q", rs.TransactionID)
@ -100,7 +101,7 @@ func TestClient_Initialize(t *testing.T) {
)
must(t, err)
rs, err := c.Initialize(datatrans.RequestInitialize{
rs, err := c.Initialize(context.Background(), datatrans.RequestInitialize{
Currency: "CHF",
RefNo: "872732",
Amount: 1337,
@ -170,7 +171,7 @@ func TestClient_AliasDelete_Error(t *testing.T) {
)
must(t, err)
err = c.AliasDelete("3469efdbbdcb043e56b19ffca69a8be0c5524d89")
err = c.AliasDelete(context.Background(), "3469efdbbdcb043e56b19ffca69a8be0c5524d89")
var detailErr datatrans.ErrorResponse
errors.As(err, &detailErr)