mntx error codes update
This commit is contained in:
@@ -166,25 +166,16 @@ func (c *Client) sendTokenization(ctx context.Context, req CardTokenizeRequest)
|
||||
}
|
||||
}
|
||||
|
||||
if apiResp.Operation.RequestID != "" {
|
||||
result.ProviderRequestID = apiResp.Operation.RequestID
|
||||
} else if apiResp.RequestID != "" {
|
||||
result.ProviderRequestID = apiResp.RequestID
|
||||
}
|
||||
result.ProviderStatus = strings.TrimSpace(apiResp.Status)
|
||||
if result.ProviderStatus == "" {
|
||||
result.ProviderStatus = strings.TrimSpace(apiResp.Operation.Status)
|
||||
}
|
||||
result.ProviderRequestID = providerRequestID(apiResp)
|
||||
result.ProviderStatus = providerStatus(apiResp)
|
||||
|
||||
if !result.Accepted {
|
||||
result.ErrorCode = apiResp.Code
|
||||
if result.ErrorCode == "" {
|
||||
errorCode, errorMessage := providerError(apiResp)
|
||||
if !result.Accepted || isProviderStatusError(result.ProviderStatus) {
|
||||
result.ErrorCode = errorCode
|
||||
if !result.Accepted && result.ErrorCode == "" {
|
||||
result.ErrorCode = http.StatusText(resp.StatusCode)
|
||||
}
|
||||
result.ErrorMessage = apiResp.Message
|
||||
if result.ErrorMessage == "" {
|
||||
result.ErrorMessage = apiResp.Operation.Message
|
||||
}
|
||||
result.ErrorMessage = errorMessage
|
||||
}
|
||||
|
||||
c.logger.Info("Monetix tokenization response",
|
||||
@@ -288,25 +279,16 @@ func (c *Client) send(ctx context.Context, req any, path string, dispatchLog fun
|
||||
}
|
||||
}
|
||||
|
||||
if apiResp.Operation.RequestID != "" {
|
||||
result.ProviderRequestID = apiResp.Operation.RequestID
|
||||
} else if apiResp.RequestID != "" {
|
||||
result.ProviderRequestID = apiResp.RequestID
|
||||
}
|
||||
result.ProviderStatus = strings.TrimSpace(apiResp.Status)
|
||||
if result.ProviderStatus == "" {
|
||||
result.ProviderStatus = strings.TrimSpace(apiResp.Operation.Status)
|
||||
}
|
||||
result.ProviderRequestID = providerRequestID(apiResp)
|
||||
result.ProviderStatus = providerStatus(apiResp)
|
||||
|
||||
if !result.Accepted {
|
||||
result.ErrorCode = apiResp.Code
|
||||
if result.ErrorCode == "" {
|
||||
errorCode, errorMessage := providerError(apiResp)
|
||||
if !result.Accepted || isProviderStatusError(result.ProviderStatus) {
|
||||
result.ErrorCode = errorCode
|
||||
if !result.Accepted && result.ErrorCode == "" {
|
||||
result.ErrorCode = http.StatusText(resp.StatusCode)
|
||||
}
|
||||
result.ErrorMessage = apiResp.Message
|
||||
if result.ErrorMessage == "" {
|
||||
result.ErrorMessage = apiResp.Operation.Message
|
||||
}
|
||||
result.ErrorMessage = errorMessage
|
||||
}
|
||||
|
||||
if responseLog != nil {
|
||||
@@ -324,6 +306,32 @@ func normalizeExpiryYear(year int) int {
|
||||
return year
|
||||
}
|
||||
|
||||
func providerRequestID(resp APIResponse) string {
|
||||
return firstNonEmpty(resp.Operation.RequestID, resp.RequestID)
|
||||
}
|
||||
|
||||
func providerStatus(resp APIResponse) string {
|
||||
return firstNonEmpty(resp.Status, resp.Operation.Status)
|
||||
}
|
||||
|
||||
func providerError(resp APIResponse) (code, message string) {
|
||||
return firstNonEmpty(resp.Code, resp.Operation.Code), firstNonEmpty(resp.Message, resp.Operation.Message)
|
||||
}
|
||||
|
||||
func isProviderStatusError(status string) bool {
|
||||
return strings.EqualFold(strings.TrimSpace(status), "error")
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
trimmed := strings.TrimSpace(value)
|
||||
if trimmed != "" {
|
||||
return trimmed
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func normalizeRequestExpiryYear(req any) {
|
||||
switch r := req.(type) {
|
||||
case *CardPayoutRequest:
|
||||
|
||||
@@ -175,6 +175,99 @@ func TestSendCardPayout_HTTPError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendCardPayout_HTTPAcceptedBodyErrorStillAccepted(t *testing.T) {
|
||||
httpClient := &http.Client{
|
||||
Transport: roundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
||||
body := `{"status":"error","code":"3062","message":"Payment details not received"}`
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(strings.NewReader(body)),
|
||||
Header: http.Header{"Content-Type": []string{"application/json"}},
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
cfg := Config{
|
||||
BaseURL: "https://monetix.test",
|
||||
SecretKey: "secret",
|
||||
}
|
||||
client := NewClient(cfg, httpClient, zap.NewNop())
|
||||
|
||||
req := CardPayoutRequest{
|
||||
General: General{ProjectID: 1, PaymentID: "payout-1"},
|
||||
Customer: Customer{
|
||||
ID: "cust-1",
|
||||
FirstName: "Jane",
|
||||
LastName: "Doe",
|
||||
IP: "203.0.113.10",
|
||||
},
|
||||
Payment: Payment{Amount: 1000, Currency: "RUB"},
|
||||
Card: Card{PAN: "4111111111111111", Year: 2030, Month: 12, CardHolder: "JANE DOE"},
|
||||
}
|
||||
|
||||
result, err := client.CreateCardPayout(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
if !result.Accepted {
|
||||
t.Fatalf("expected accepted response")
|
||||
}
|
||||
if result.ProviderStatus != "error" {
|
||||
t.Fatalf("expected provider status error, got %q", result.ProviderStatus)
|
||||
}
|
||||
if result.ErrorCode != "3062" {
|
||||
t.Fatalf("expected error code %q, got %q", "3062", result.ErrorCode)
|
||||
}
|
||||
if result.ErrorMessage != "Payment details not received" {
|
||||
t.Fatalf("expected error message, got %q", result.ErrorMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendCardPayout_HTTPErrorFallsBackToOperationCode(t *testing.T) {
|
||||
httpClient := &http.Client{
|
||||
Transport: roundTripperFunc(func(r *http.Request) (*http.Response, error) {
|
||||
body := `{"operation":{"code":"3061","message":"Transaction not found"}}`
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusBadRequest,
|
||||
Body: io.NopCloser(strings.NewReader(body)),
|
||||
Header: http.Header{"Content-Type": []string{"application/json"}},
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
cfg := Config{
|
||||
BaseURL: "https://monetix.test",
|
||||
SecretKey: "secret",
|
||||
}
|
||||
client := NewClient(cfg, httpClient, zap.NewNop())
|
||||
|
||||
req := CardPayoutRequest{
|
||||
General: General{ProjectID: 1, PaymentID: "payout-1"},
|
||||
Customer: Customer{
|
||||
ID: "cust-1",
|
||||
FirstName: "Jane",
|
||||
LastName: "Doe",
|
||||
IP: "203.0.113.10",
|
||||
},
|
||||
Payment: Payment{Amount: 1000, Currency: "RUB"},
|
||||
Card: Card{PAN: "4111111111111111", Year: 2030, Month: 12, CardHolder: "JANE DOE"},
|
||||
}
|
||||
|
||||
result, err := client.CreateCardPayout(context.Background(), req)
|
||||
if err != nil {
|
||||
t.Fatalf("expected no error, got %v", err)
|
||||
}
|
||||
if result.Accepted {
|
||||
t.Fatalf("expected rejected response")
|
||||
}
|
||||
if result.ErrorCode != "3061" {
|
||||
t.Fatalf("expected error code %q, got %q", "3061", result.ErrorCode)
|
||||
}
|
||||
if result.ErrorMessage != "Transaction not found" {
|
||||
t.Fatalf("expected error message, got %q", result.ErrorMessage)
|
||||
}
|
||||
}
|
||||
|
||||
type errorReadCloser struct {
|
||||
err error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user