mobilepay

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Feb 20, 2022 License: MIT Imports: 18 Imported by: 0

README

mobilepay-go

The unofficial MobilePay Go client library.

Build Status Test suite Status Go Report Card GoDoc codecov

Installation

$ go get -u github.com/steffen25/mobilepay-go

Then, reference mobilepay-go in a Go program with import:

import (
    "github.com/steffen25/mobilepay-go"
)

Documentation

Below are a few simple examples:

Initialize a Mobilepay client
cfg := &mobilepay.Config{
    HTTPClient: nil,
    Logger:     nil,
    URL:        mobilepay.DefaultBaseURL,
}

mp := mobilepay.New("client_id", "api_key", cfg)

The config properties allows you to use custom configured values if you would like. Otherwise the client will fall back to use a default value.

E.g. you might want to use a HTTP client that automatically retries request if a server error occurs. https://github.com/hashicorp/go-retryablehttp

The library will default to the production base URL if not set. You can use the constants defined by the mobilepay package if you would like to try out the sandbox environment (highly recommended). Use either the mobilepay.DefaultBaseURL or mobilepay.TestBaseUrl.

All the examples below will use the reference mp as a reference to the client.

Payments

Get all payments

opts := mobilepay.ListOptions{
    PageSize:   10,
    PageNumber: 1,
}

ctx := context.TODO()

payments, err := mp.Payment.Get(ctx, opts)

Get single payment details

ctx := context.TODO()

payment, err := mp.Payment.Find(ctx, "payment_id")

Create payment

params := &mobilepay.PaymentParams{
    Amount:         1050,
    IdempotencyKey: "223dbe4e-2d3b-4484-b870-6c86cff2c07b",
    PaymentPointId: "8f8ed17f-f310-4f40-a7a4-df78185efbdd",
    RedirectUri:    "myapp://redirect",
    Reference:      "payment-1",
    Description:    "test payment #1",
}

ctx := context.TODO()

payment, err := mp.Payment.Create(ctx, params)

Capture payment

ctx := context.TODO()

err := mp.Payment.Capture(ctx, "payment_id", 1050)

The amount is specified as an integer and is in cents which in danish terms is 'ører'.

Cancel payment

ctx := context.TODO()

err := mp.Payment.Cancel(ctx, "payment_id")

List payment refunds

opts := &mobilepay.RefundsListOptions{
    ListOptions: mobilepay.ListOptions{
        PageSize:   10,
        PageNumber: 1,
    },
    PaymentId:      "payment_id",
    PaymentPointId: "payment_point_id",
    CreatedBefore:  "2020-01-02T15:04",
    CreatedAfter:   "2021-01-02T15:04",
}

ctx := context.TODO()

err := mp.Payment.Refunds(ctx, opts)

Create payment refund

params := &mobilepay.PaymentRefundParams{
    PaymentId:      "223dbe4e-2d3b-4484-b870-6c86cff2c07b",
    Amount:         550
    IdempotencyKey: "223dbe4e-2d3b-4484-b870-6c86cff2c07b",
    Reference:      "payment-1",
    Description:    "this is a test payment",
}

ctx := context.TODO()

err := mp.Payment.Refunds(ctx, params)
Webhooks

Get single webhook

ctx := context.TODO()

webhook, err := mp.Webhook.Find(ctx, "webhook_id")

Get all merchant's webhooks

ctx := context.TODO()

webhooks, err := mp.Webhook.Get(ctx)

Create webhook

ctx := context.TODO()

// configure these events to match your needs.
events := []mobilepay.WebhookEvent{
    mobilepay.PaymentReserved.Name(),
    mobilepay.PaymentExpired.Name(),
}

// change the base url accordingly
params := &mobilepay.WebhookCreateParams{
    Events: events,
    Url:    "https://my-api.com/webhooks",
}

webhook, err := mp.Webhook.Create(ctx, params)

Update webhook

ctx := context.TODO()

events := []mobilepay.WebhookEvent{
    mobilepay.PaymentPointActivated.Name(),
}

params := &mobilepay.WebhookUpdateParams{
    Events: events,
    Url:    "https://my-api.com/webhooks",
}

webhook, err := mp.Webhook.Update(ctx, "webhook_id", params)

Delete webhook

ctx := context.TODO()

err := mp.Webhook.Delete(ctx, "webhook_id")
Verifying webhooks

This library comes with a built in webhook verifier that you can use ensure webhooks was sent by MobilePay.

The example below illustrates how you can verify incoming MobilePay webhooks using the standard library but this verifier could be used with any of the major router libraries out there.

func main() {
    mux := http.NewServeMux()
    
    successHandler := http.HandlerFunc(mobilepaySuccesHandler)
    mux.Handle("/mobilepay/webhooks", mobilepayWebhooks(successHandler, "webhook_url", "webhook_signature_key"))
}

// middleware to verify webhook was sent by MobilePay.
func mobilepayWebhooks(next http.Handler, webhookUrl, webhookSignature string) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        verifier, err := mobilepay.NewWebhooksVerifier(r.Header, webhookUrl, webhookSignature)
        if err != nil {
            // handle error
        }
        
        body, err := ioutil.ReadAll(r.Body)
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            return
        }
        
        // rewind the body
        r.Body = ioutil.NopCloser(bytes.NewBuffer(body))
        
        _, err = verifier.Write(body)
        if err != nil {
            // handle error
        }
        
        err = verifier.Ensure()
        if err != nil {
            // could not verify mobilepay signature.
            w.WriteHeader(http.StatusInternalServerError)
            return
        }
        
        // Signature is OK.
        // Go to next handler in the call stack (mobilepaySuccesHandler)
        next.ServeHTTP(w, r)
    })
}

func mobilepaySuccesHandler(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Webhook OK"))
}

Contributing

You are more than welcome to contribute to this project. Fork and make a Pull Request, or create an Issue if you see any problem.

MobilePay documentation

License

MIT

Documentation

Index

Constants

View Source
const (
	LibraryVersion = "1.0.0"
	DefaultBaseURL = "https://api.mobilepay.dk"
	TestBaseUrl    = "https://api.sandbox.mobilepay.dk"

	DefaultTimeout = 10 * time.Second
)

https://mobilepaydev.github.io/MobilePay-Payments-API/docs/payments-refunds/create-payments

Variables

View Source
var (
	ErrMissingVerifierProperties = errors.New("missing required verifier properties signature or webhook url")
)

Functions

func CheckResponse added in v0.0.3

func CheckResponse(r *http.Response) error

func DoRequestWithClient added in v0.0.3

func DoRequestWithClient(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error)

Types

type ArgError added in v0.0.3

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

ArgError is an error that represents an error with an input to mobilepay app payment. It identifies the argument and the cause (if possible).

func (*ArgError) Error added in v0.0.3

func (e *ArgError) Error() string

type Client added in v0.0.3

type Client struct {

	// Base URL for API requests.
	BaseURL *url.URL

	// User agent for client
	UserAgent string

	Logger LeveledLoggerInterface

	// MobilePay API services used for communicating with the API.
	Payment *PaymentServiceOp // we are using a struct over an interface to support multiple interfaces implemented by the struct properties.
	Webhook WebhookService
	// contains filtered or unexported fields
}

func New added in v0.0.3

func New(IbmClientId, apiKey string, config *Config) *Client

func (*Client) Do added in v0.0.3

func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error)

func (*Client) NewRequest added in v0.0.3

func (c *Client) NewRequest(ctx context.Context, method, urlStr string, body interface{}) (*http.Request, error)

type ClientOpt added in v0.0.3

type ClientOpt func(*Client) error

ClientOpt are options for New.

type Config

type Config struct {
	HTTPClient *http.Client
	Logger     LeveledLoggerInterface
	URL        string
}

URL is the base url to the Mobilepay API. You can use the constants defined in this package: DefaultBaseURL or TestBaseUrl

type ConflictError added in v0.0.3

type ConflictError struct {
	Code          string `json:"code"`
	Message       string `json:"message"`
	CorrelationID string `json:"correlationId"`
	Origin        string `json:"origin"`
}

type CreatePaymentResponse added in v0.0.3

type CreatePaymentResponse struct {
	PaymentId               string `json:"paymentId"`
	MobilePayAppRedirectUri string `json:"mobilePayAppRedirectUri"`
}

type ErrorResponse added in v0.0.3

type ErrorResponse struct {
	// HTTP response that caused this error
	Response *http.Response `json:"-"`

	// Error message
	Message    string         `json:"message,omitempty"`
	Conflict   *ConflictError `json:"conflict"`
	StatusCode int            `json:"statusCode"`
}

An ErrorResponse reports the error caused by an API request

func (*ErrorResponse) Error added in v0.0.3

func (r *ErrorResponse) Error() string

type GetWebhookRequest added in v0.0.3

type GetWebhookRequest struct {
}

type GetWebhookResponse added in v0.0.3

type GetWebhookResponse struct {
	Webhooks []Webhook `json:"webhooks"`
}

type Level added in v0.0.3

type Level uint32

Level represents a logging level.

const (
	// LevelNull sets a logger to show no messages at all.
	LevelNull Level = 0

	// LevelError sets a logger to show error messages only.
	LevelError Level = 1

	// LevelWarn sets a logger to show warning messages or anything more
	// severe.
	LevelWarn Level = 2

	// LevelInfo sets a logger to show informational messages or anything more
	// severe.
	LevelInfo Level = 3

	// LevelDebug sets a logger to show informational messages or anything more
	// severe.
	LevelDebug Level = 4
)

type LeveledLogger added in v0.0.3

type LeveledLogger struct {
	// Level is the minimum logging level that will be emitted by this logger.
	//
	// For example, a Level set to LevelWarn will emit warnings and errors, but
	// not informational or debug messages.
	//
	// Always set this with a constant like LevelWarn because the individual
	// values are not guaranteed to be stable.
	Level Level
	// contains filtered or unexported fields
}

LeveledLogger is a leveled logger implementation.

It prints warnings and errors to `os.Stderr` and other messages to `os.Stdout`.

func (*LeveledLogger) Debugf added in v0.0.3

func (l *LeveledLogger) Debugf(format string, v ...interface{})

Debugf logs a debug message using Printf conventions.

func (*LeveledLogger) Errorf added in v0.0.3

func (l *LeveledLogger) Errorf(format string, v ...interface{})

Errorf logs a warning message using Printf conventions.

func (*LeveledLogger) Infof added in v0.0.3

func (l *LeveledLogger) Infof(format string, v ...interface{})

Infof logs an informational message using Printf conventions.

func (*LeveledLogger) Warnf added in v0.0.3

func (l *LeveledLogger) Warnf(format string, v ...interface{})

Warnf logs a warning message using Printf conventions.

type LeveledLoggerInterface added in v0.0.3

type LeveledLoggerInterface interface {
	// Debugf logs a debug message using Printf conventions.
	Debugf(format string, v ...interface{})

	// Errorf logs a warning message using Printf conventions.
	Errorf(format string, v ...interface{})

	// Infof logs an informational message using Printf conventions.
	Infof(format string, v ...interface{})

	// Warnf logs a warning message using Printf conventions.
	Warnf(format string, v ...interface{})
}

LeveledLoggerInterface provides a basic leveled logging interface for printing debug, informational, warning, and error messages.

var DebugLeveledLogger LeveledLoggerInterface = &LeveledLogger{
	Level: LevelDebug,
}
var DefaultLeveledLogger LeveledLoggerInterface = &LeveledLogger{
	Level: LevelError,
}

DefaultLeveledLogger is the default logger that the library will use to log errors, warnings, and informational messages.

var InfoLeveledLogger LeveledLoggerInterface = &LeveledLogger{
	Level: LevelDebug,
}
var WarnLeveledLogger LeveledLoggerInterface = &LeveledLogger{
	Level: LevelWarn,
}

type ListOptions added in v0.0.3

type ListOptions struct {
	PageSize   int `url:"pageSize"`
	PageNumber int `url:"pageNumber"`
}

type Payment added in v0.0.3

type Payment struct {
	PaymentId               string `json:"paymentId,omitempty"`
	Amount                  int    `json:"amount,omitempty"`
	Description             string `json:"description,omitempty"`
	PaymentPointId          string `json:"paymentPointId,omitempty"`
	Reference               string `json:"reference,omitempty"`
	MobilePayAppRedirectUri string `json:"mobilePayAppRedirectUri,omitempty"`
	State                   string `json:"state,omitempty"`
	InitiatedOn             string `json:"initiatedOn,omitempty"`
	LastUpdatedOn           string `json:"lastUpdatedOn,omitempty"`
	MerchantId              string `json:"merchantId,omitempty"`
	IsoCurrencyCode         string `json:"isoCurrencyCode,omitempty"`
	PaymentPointName        string `json:"paymentPointName,omitempty"`
}

type PaymentParams added in v0.0.3

type PaymentParams struct {
	Amount         int    `json:"amount"`
	IdempotencyKey string `json:"idempotencyKey"`
	PaymentPointId string `json:"paymentPointId"`
	RedirectUri    string `json:"redirectUri"`
	Reference      string `json:"reference"`
	Description    string `json:"description"`
}

type PaymentService added in v0.0.3

type PaymentService interface {
	Get(context.Context, ListOptions) (*PaymentsRoot, error)
	Find(context.Context, string) (*Payment, error)
	Create(context.Context, *PaymentParams) (*CreatePaymentResponse, error)

	Cancel(ctx context.Context, paymentId string) error
	Capture(ctx context.Context, paymentId string, amount int) error
}

type PaymentServiceOp added in v0.0.3

type PaymentServiceOp struct {
	Refund RefundService
	// contains filtered or unexported fields
}

func (*PaymentServiceOp) Cancel added in v0.0.3

func (ps *PaymentServiceOp) Cancel(ctx context.Context, paymentId string) error

func (*PaymentServiceOp) Capture added in v0.0.3

func (ps *PaymentServiceOp) Capture(ctx context.Context, paymentId string, amount int) error

func (*PaymentServiceOp) Create added in v0.0.3

func (ps *PaymentServiceOp) Create(ctx context.Context, paymentParams *PaymentParams) (*CreatePaymentResponse, error)

func (*PaymentServiceOp) Find added in v0.0.3

func (ps *PaymentServiceOp) Find(ctx context.Context, paymentId string) (*Payment, error)

func (PaymentServiceOp) Get added in v0.0.3

type PaymentsRoot added in v0.0.3

type PaymentsRoot struct {
	Payments       []Payment `json:"payments"`
	PageSize       int       `json:"pageSize"`
	NextPageNumber int       `json:"nextPageNumber"`
}

type Refund added in v0.0.3

type Refund struct {
	RefundId        string `json:"refundId"`
	PaymentId       string `json:"paymentId"`
	Amount          int    `json:"amount"`
	RemainingAmount int    `json:"remainingAmount,omitempty"`
	Description     string `json:"description"`
	Reference       string `json:"reference"`
	CreatedOn       string `json:"createdOn"`
}

type RefundParams added in v0.0.3

type RefundParams struct {
	IdempotencyKey string `json:"idempotencyKey"`
	PaymentId      string `json:"paymentId"`
	Amount         int    `json:"amount"`
	Reference      string `json:"reference"`
	Description    string `json:"description"`
}

type RefundService added in v0.0.3

type RefundService interface {
	List(ctx context.Context, opt *RefundsListOptions) (*RefundsRoot, error)
	Create(ctx context.Context, createRequest *RefundParams) (*Refund, error)
}

type RefundServiceOp added in v0.0.3

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

func (*RefundServiceOp) Create added in v0.0.3

func (rs *RefundServiceOp) Create(ctx context.Context, refundParams *RefundParams) (*Refund, error)

func (RefundServiceOp) List added in v0.0.3

type RefundsListOptions added in v0.0.3

type RefundsListOptions struct {
	ListOptions
	PaymentId      string `url:"paymentId"`
	PaymentPointId string `url:"paymentPointId,omitempty"`
	CreatedBefore  string `url:"createdBefore,omitempty"`
	CreatedAfter   string `url:"createdAfter,omitempty"`
}

type RefundsRoot added in v0.0.3

type RefundsRoot struct {
	Refunds        []Refund `json:"refunds"`
	PageSize       int      `json:"pageSize"`
	NextPageNumber int      `json:"nextPageNumber"`
}

type RequestCompletionCallback added in v0.0.3

type RequestCompletionCallback func(*http.Request, *http.Response)

RequestCompletionCallback defines the type of the request callback function

type Response added in v0.0.3

type Response struct {
	*http.Response
}

type Webhook added in v0.0.3

type Webhook struct {
	WebhookId    string         `json:"webhookId"`
	SignatureKey string         `json:"signatureKey"`
	Url          string         `json:"url"`
	Events       []WebhookEvent `json:"events"`
}

type WebhookCreateParams added in v0.0.3

type WebhookCreateParams struct {
	// Find of subscribed events.
	Events []WebhookEvent `json:"events"`
	// URL to where webhook requests will be sent. Must be HTTPS. Scheme and host will be converted to lower case. Result can be seen in the response.
	Url string `json:"url"`
}

WebhookCreateParams represents a request to create a payment.

type WebhookEvent added in v0.0.3

type WebhookEvent string

type WebhookEventEnum added in v0.0.3

type WebhookEventEnum int
const (
	Unknown WebhookEventEnum = iota
	PaymentReserved
	PaymentExpired
	PaymentPointActivated
)

func (WebhookEventEnum) Name added in v0.0.3

func (webhookEvent WebhookEventEnum) Name() WebhookEvent

type WebhookService added in v0.0.3

type WebhookServiceOp added in v0.0.3

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

func (*WebhookServiceOp) Create added in v0.0.3

func (s *WebhookServiceOp) Create(ctx context.Context, createRequest *WebhookCreateParams) (*Webhook, error)

Create webhook

func (*WebhookServiceOp) Delete added in v0.0.3

func (s *WebhookServiceOp) Delete(ctx context.Context, webhookId string) error

func (*WebhookServiceOp) Find added in v0.0.3

func (s *WebhookServiceOp) Find(ctx context.Context, webhookId string) (*Webhook, error)

Get individual webhook. It requires a non-empty webhook id.

func (WebhookServiceOp) Get added in v0.0.3

List all webhooks.

func (WebhookServiceOp) Update added in v0.0.3

func (s WebhookServiceOp) Update(ctx context.Context, webhookId string, request *WebhookUpdateParams) (*Webhook, error)

type WebhookUpdateParams added in v0.0.3

type WebhookUpdateParams struct {
	Url    string         `json:"url"`
	Events []WebhookEvent `json:"events"`
}

WebhookUpdateParams represents a request to update a webhook record.

type WebhooksRoot added in v0.0.3

type WebhooksRoot struct {
	Webhooks []Webhook `json:"webhooks"`
}

webhooksRoot represents a response from the MobilePay App Payment API

type WebhooksVerifier added in v0.0.3

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

func NewWebhooksVerifier added in v0.0.3

func NewWebhooksVerifier(header http.Header, webhookUrl, webhookSignatureKey string) (wv WebhooksVerifier, err error)

NewWebhooksVerifier is a helper function to verify incoming webhooks from Mobilepay. See https://mobilepaydev.github.io/MobilePay-Payments-API/docs/webhooks-api webhookUrl is your webhook url that you used to create the webhook. webhookSignatureKey is returned by Mobilepay when you create a webhook.

func (WebhooksVerifier) Ensure added in v0.0.3

func (v WebhooksVerifier) Ensure() error

func (*WebhooksVerifier) Write added in v0.0.3

func (v *WebhooksVerifier) Write(body []byte) (n int, err error)

Jump to

Keyboard shortcuts

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