maib

package module
v2.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 8, 2025 License: LGPL-3.0 Imports: 11 Imported by: 0

README

Go MAIB ECommerce SDK

Go Reference

Copyright (C) 2025 Nejintev Nicolai

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this library.  If not, see <https://www.gnu.org/licenses/>.

This library provides tools to interact with MAIB ECommerce in a type safe way.

This library is UNOFFICIAL, inspired by public Integration Guide and implementations shared by MAIB.

Unlike other implementations, you don't need to run any openssl commands to change the certificate's format. Only the default .pfx pkcs#12 file is needed.

Usage

To install, run the following:

go get github.com/NikSays/go-maib-ecomm/v2

Then use the package maib:

package main
import "github.com/NikSays/go-maib-ecomm/v2"

func main()  {
    conf := maib.Config{/* ... */}
    // ...
}

Documentation

Documentation and examples are available at Go Reference.

Testing

If you need to regenerate the testing certificates, run the ./genCrt.sh script in the ./testdata folder.

To test the package just run go test ./... .

Documentation

Overview

Package maib provides tools to interact with the MAIB ECommerce system in a type safe way.

Requirements

To use this module you should:

  • Understand how MAIB ECommerce works
  • Have a .pfx certificate
  • Register as a merchant in MAIB

Usage

  1. Use NewClient to set up a Client that communicates with the MAIB ECommerce system.
  2. Send a Request with Client.Send (The requests described in the ECommerce documentation are implemented in the `requests` package).
  3. Decode the returned map into a result struct with requests.DecodeResult.

Error Handling

Use errors.As to check the type and the contents of the errors returned by the Client:

  • ValidationError is returned before sending the request if it has failed validation.
  • ECommError is returned if the response has a non-200 code, or its body starts with "error:".
  • ParseError is returned if the response has an invalid structure, or a response field has an unexpected datatype.

See the example to get an understanding of the full flow.

Example
// In this example we will
// * Create a Client
// * Execute an SMS transaction and decode the response
// * Check the created transaction's status
// Errors are ignored for brevity, please handle them in your code.

// Create new client to send requests to MAIB ECommerce
client, _ := NewClient(Config{
	PFXPath:                 "cert.pfx",
	Passphrase:              "p4ssphr4s3",
	MerchantHandlerEndpoint: "https://example.org/handler",
})

// Execute an SMS transaction (-v) for 10 Euro.
// Equivalent to this POST request:
// command=v&amount=1000&currency=978&language=en&client_ip_addr=127.0.0.1&description=10+EUR+will+be+charged
res, _ := client.Send(context.TODO(), requests.RegisterTransaction{
	TransactionType: requests.RegisterTransactionSMS,
	Amount:          1000,
	Currency:        CurrencyEUR,
	ClientIPAddress: "127.0.0.1",
	Description:     "10 EUR will be charged",
	Language:        LanguageEnglish,
})

// Decode response map into RegisterTransactionResult struct,
// to get the ID of the created transaction.
newTransaction, _ := requests.DecodeResponse[requests.RegisterTransactionResult](res)

// Send a Transaction Status request with a timeout.
// Equivalent to this POST request:
// command=c&trans_id=<TransactionID>&client_ip_addr=127.0.0.1
ctx, _ := context.WithTimeout(context.Background(), time.Minute)
res, _ = client.Send(ctx, requests.TransactionStatus{
	TransactionID:   newTransaction.TransactionID,
	ClientIPAddress: "127.0.0.1",
})

// Decode response map into TransactionStatusResult struct,
// to get the transaction result.
status, _ := requests.DecodeResponse[requests.TransactionStatusResult](res)

// Print the result of the transaction
fmt.Println(status.Result)
Example (ErrorHandling)
// Send a request with a client.
client, _ := NewClient(Config{ /* ... */ })
_, err := client.Send(context.TODO(), requests.RegisterTransaction{ /* ... */ })

// The target of errors.As should be a pointer to a type that implements error.
// Since the Error method is defined on *ValidationError, the second argument to
// errors.As should be **ValidationError.
//
// The same principle is used for ECommError and ParseError.
if valErr := (&ValidationError{}); errors.As(err, &valErr) {
	fmt.Printf("Invalid field %s: %s", valErr.Field, valErr.Description)
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client allows sending requests to the MAIB ECommerce system using HTTPS with mutual TLS. It is safe for concurrent use.

Client validates the Request before sending it, and checks the response for errors. The response is then parsed into a map that can be decoded into a result struct using requests.DecodeResponse.

Must be initiated with NewClient.

func NewClient

func NewClient(config Config) (*Client, error)

NewClient reads and parses the PFX certificate file and returns a *Client that uses the certificate for mutual TLS.

func (*Client) Send

func (c *Client) Send(ctx context.Context, req Request) (map[string]any, error)

Send validates a Request and sends it to the ECommerce system. The value returned on success can be parsed into a result struct using requests.DecodeResponse.

The request is cancelled when the context is done.

type Config

type Config struct {
	// Path to .pfx certificate issued by MAIB.
	PFXPath string
	// Passphrase to the certificate.
	Passphrase string
	// API communication URL issued by MAIB.
	MerchantHandlerEndpoint string
}

Config is the configuration required to set up a Client.

type Currency

type Currency int

Currency is an alias type for int. Valid values are 3 digit ISO4217 codes. The most common codes are exported by this package.

const (
	// CurrencyMDL is the ISO4217 code for Moldovan Lei.
	CurrencyMDL Currency = 498

	// CurrencyEUR is the ISO4217 code for Euro.
	CurrencyEUR Currency = 978

	// CurrencyUSD is the ISO4217 code for United States Dollar.
	CurrencyUSD Currency = 840
)

type ECommError

type ECommError struct {
	// HTTP status code.
	Code int

	// Response body.
	Body string
}

ECommError is returned when the ECommerce system responds with a non-200 status, or when the response body starts with "error:".

func (*ECommError) Error

func (e *ECommError) Error() string

type Language

type Language string

Language is an alias type for string. Valid values are language identifiers that the merchant has sent to MAIB. The default identifiers are exported by this package.

const (
	LanguageRomanian Language = "ro"
	LanguageRussian  Language = "ru"
	LanguageEnglish  Language = "en"
)

type ParseError

type ParseError struct {
	// Underlying error.
	Err error

	// Response body that couldn't be parsed.
	Body string
}

ParseError is returned when the response from the ECommerce system doesn't follow "KEY: value" format, or when a field has an unexpected type.

func (*ParseError) Error

func (e *ParseError) Error() string

func (*ParseError) Unwrap

func (e *ParseError) Unwrap() error

Unwrap returns the underlying error, for usage with errors.As.

type PayloadField

type PayloadField string

PayloadField contains the names of the payload fields. Used in ValidationError.

const (
	FieldTransactionID   PayloadField = "trans_id"
	FieldAmount          PayloadField = "amount"
	FieldCurrency        PayloadField = "currency"
	FieldClientIPAddress PayloadField = "client_ip_addr"
	FieldDescription     PayloadField = "description"
	FieldLanguage        PayloadField = "language"
	FieldBillerClientID  PayloadField = "biller_client_id"
	FieldPerspayeeExpiry PayloadField = "prespayee_expiry"
	FieldCommand         PayloadField = "command"
)

type Request

type Request interface {
	// Values validates the request and returns the payload as a URL value map, that
	// can be encoded into a querystring to be sent to the ECommerce system.
	Values() (url.Values, error)
}

Request is a payload that can be sent to the ECommerce system.

type ResultEnum

type ResultEnum string

ResultEnum holds the possible values of the RESULT field returned by the ECommerce system.

const (
	// ResultOk - the transaction has successfully completed.
	ResultOk ResultEnum = "OK"

	// ResultFailed - the transaction has failed.
	ResultFailed ResultEnum = "FAILED"

	// ResultCreated - the transaction is just registered in the system. Client
	// didn't input their card information yet.
	ResultCreated ResultEnum = "CREATED"

	// ResultPending - the transaction is not complete yet.
	ResultPending ResultEnum = "PENDING"

	// ResultDeclined - the transaction was declined by EComm.
	ResultDeclined ResultEnum = "DECLINED"

	// ResultReversed - the transaction was reversed.
	ResultReversed ResultEnum = "REVERSED"

	// ResultAutoReversed - the transaction was reversed by autoreversal.
	ResultAutoReversed ResultEnum = "AUTOREVERSED"

	// ResultTimeout - the transaction has timed out.
	ResultTimeout ResultEnum = "TIMEOUT"
)

type ResultPSEnum

type ResultPSEnum string

ResultPSEnum holds the possible values for the RESULT_PS field returned by the ECommerce system.

const (
	// ResultPSActive - the transaction was registered and payment is not completed
	// yet.
	ResultPSActive ResultPSEnum = "ACTIVE"

	// ResultPSFinished - payment was completed successfully.
	ResultPSFinished ResultPSEnum = "FINISHED"

	// ResultPSCancelled - payment was cancelled.
	ResultPSCancelled ResultPSEnum = "CANCELLED"

	// ResultPSReturned - payment was returned.
	ResultPSReturned ResultPSEnum = "RETURNED"
)

type ValidationError

type ValidationError struct {
	// Which field is malformed.
	Field PayloadField

	// Human-readable explanation of the requirements.
	Description string
}

ValidationError is triggered before sending the request to the ECommerce system, if the request has failed validation.

func (*ValidationError) Error

func (e *ValidationError) Error() string

Directories

Path Synopsis
internal
validators
Package validators provides functions to validate input without boilerplate.
Package validators provides functions to validate input without boilerplate.
Package requests contains the request structs for each of the commands available in the MAIB ECommerce.
Package requests contains the request structs for each of the commands available in the MAIB ECommerce.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL