monapay

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 17 Imported by: 0

README

MONA Pay SDK for Go

SDK Go 1.21+, zero-dependency cho MONA Pay, API ngân hàng và dịch vụ xác nhận thanh toán tự động của The MONA Group. Tiền chuyển thẳng vào tài khoản doanh nghiệp; SDK hỗ trợ VA, VietQR, webhook và Telegram.

Xác thực cho AI agent

export MONAPAY_CLIENT_ID="client-id"
export MONAPAY_CLIENT_SECRET="client-secret"
export MONAPAY_BASE_URL="https://api.monapay.vn"
client, err := monapay.NewClientFromEnv()
if err != nil { log.Fatal(err) }
profile, err := client.Me(context.Background())
qr, err := client.QR.Generate(context.Background(), qrBody)
sandbox, err := client.Sandbox.CreateTransaction(context.Background(), map[string]any{"virtual_account_number": "MONA123", "amount": 10000, "description": "AI test"})

NewClientFromEnv dùng client credentials, cache token tới gần hạn và tự lấy lại token một lần khi gặp HTTP 401. Username/password chỉ là fallback tương thích cũ, không dùng cho AI agent vì sẽ gãy khi bật 2FA.

Cài đặt

go get github.com/mona-software/monapay-go

Dùng nhanh

client, err := monapay.NewClient(monapay.Config{
    Username: os.Getenv("MONA_USERNAME"),
    Password: os.Getenv("MONA_PASSWORD"),
    ClientSecret: os.Getenv("MONA_CLIENT_SECRET"),
})
if err != nil { log.Fatal(err) }

profile, err := client.Me(context.Background())
hooks, err := client.Webhooks.List(context.Background())

Các resource: Keys, BankAccounts, PaymentProfile, Checkouts, VA (đăng ký + hai bước OTP), QR, Transactions, Webhooks, WebhookLogs, Sandbox, EmailConfigs, EmailLogs, EmailSuppressions. Client cache Bearer token theo hạn, lấy lại đúng một lần khi gặp HTTP 401 và tự gắn X-Client-Secret cho POST/PUT/DELETE.

Trang thanh toán (hosted checkout)

checkout, err := client.Checkouts.Create(ctx, map[string]any{"amount": 250000, "order_code": "DH10234", "return_url": "https://shop.vn/payment/return"}, "")
if err != nil { log.Fatal(err) }
http.Redirect(w, r, checkout.(map[string]any)["checkout_url"].(string), http.StatusFound)
if event.Type == "CHECKOUT_PAID" {
    fulfillOnce(event.Data["order_code"])
}

SDK tự sinh Idempotency-Key cho Create và Cancel; truyền đối số key cuối khi anh chị cần dùng key riêng. Nguồn sự thật để giao hàng là webhook CHECKOUT_PAID hoặc kết quả Get, không phải redirect trình duyệt.

Đọc giao dịch mới kể từ mốc đã lưu:

it := client.Transactions.Iterate(ctx, "MONA000001", monapay.TransactionOptions{
    Limit: 100,
    SinceID: "FT26240001234",
})
for it.Next() {
    transaction := it.Value().(map[string]any)
    // Lưu transaction_code làm idempotency key.
}
if err := it.Err(); err != nil { log.Fatal(err) }

SinceID là helper phía SDK: iterator dừng trước item có id hoặc transaction_code trùng mốc. SDK không gửi query since_id, vì API hiện chưa hỗ trợ tham số đó.

Xác thực webhook trên raw bytes trước khi parse JSON:

result, err := monapay.VerifyWebhook(rawBody, timestampHeader, signatureHeader, secret)
if err != nil || !result.OK { /* trả 401 */ }

Ví dụ server đầy đủ: examples/webhook/main.go. Chạy test offline bằng go test ./....

Docs: https://monapay.vn/docs · Hotline 1900 636 648 · info@themona.global. MONA Pay miễn phí hoàn toàn.

English

Zero-dependency Go 1.21+ SDK for MONA Pay. It includes automatic login/token caching, one 401 refresh, virtual accounts and both OTP steps, VietQR, paginated transaction iteration with a client-side SinceID checkpoint, webhook configuration/logs/retry, and constant-time webhook verification. See the example and API above.

MIT © The MONA Group.

MONA Pay is part of MONA Cloud by The MONA Group.

MONA Pay thuộc bộ MONA Cloud của The MONA Group.

Documentation

Index

Constants

View Source
const DefaultBaseURL = "https://api.monapay.vn"

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	Status int
	Body   any
	Msg    string
}

APIError describes an error response or an invalid response from MONA Pay.

func (*APIError) Error

func (e *APIError) Error() string

type BankAccountsResource

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

func (*BankAccountsResource) List

func (r *BankAccountsResource) List(ctx context.Context) (any, error)

type CheckoutOptions

type CheckoutOptions struct {
	Status, OrderCode, FromDate, ToDate string
	Page, Limit                         int
}

type CheckoutsResource

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

func (*CheckoutsResource) Cancel

func (r *CheckoutsResource) Cancel(ctx context.Context, checkoutID, key string) (any, error)

func (*CheckoutsResource) Create

func (r *CheckoutsResource) Create(ctx context.Context, body map[string]any, key string) (any, error)

func (*CheckoutsResource) Get

func (r *CheckoutsResource) Get(ctx context.Context, checkoutID string) (any, error)

func (*CheckoutsResource) List

func (r *CheckoutsResource) List(ctx context.Context, options CheckoutOptions) (any, error)

type Client

type Client struct {
	Keys              *KeysResource
	VA                *VirtualAccountsResource
	BankAccounts      *BankAccountsResource
	PaymentProfile    *PaymentProfileResource
	Checkouts         *CheckoutsResource
	QR                *QRResource
	Transactions      *TransactionsResource
	Webhooks          *WebhooksResource
	WebhookLogs       *WebhookLogsResource
	Sandbox           *SandboxResource
	EmailConfigs      *EmailConfigsResource
	EmailLogs         *EmailLogsResource
	EmailSuppressions *EmailSuppressionsResource
	// contains filtered or unexported fields
}

Client is a synchronous, safe-for-concurrent-use MONA Pay API client.

func NewClient

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

func NewClientFromEnv

func NewClientFromEnv() (*Client, error)

NewClientFromEnv creates a client from MONAPAY_CLIENT_ID, MONAPAY_CLIENT_SECRET and optional MONAPAY_BASE_URL. Username/password are a legacy fallback only and should not be used by AI agents because 2FA breaks it.

func (*Client) Me

func (c *Client) Me(ctx context.Context) (any, error)

func (*Client) SetClientSecret

func (c *Client) SetClientSecret(secret string)

type Config

type Config struct {
	ClientID     string
	Username     string
	Password     string
	ClientSecret string
	BaseURL      string
	HTTPClient   *http.Client
}

Config configures a MONA Pay client.

type EmailConfigsResource

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

func (*EmailConfigsResource) Create

func (r *EmailConfigsResource) Create(ctx context.Context, body map[string]any) (any, error)

func (*EmailConfigsResource) Get

func (r *EmailConfigsResource) Get(ctx context.Context, configID string) (any, error)

func (*EmailConfigsResource) List

func (r *EmailConfigsResource) List(ctx context.Context) (any, error)

func (*EmailConfigsResource) Remove

func (r *EmailConfigsResource) Remove(ctx context.Context, configID string) (any, error)

func (*EmailConfigsResource) ResendVerification

func (r *EmailConfigsResource) ResendVerification(ctx context.Context, configID, email string) (any, error)

func (*EmailConfigsResource) Test

func (r *EmailConfigsResource) Test(ctx context.Context, configID string) (any, error)

func (*EmailConfigsResource) Update

func (r *EmailConfigsResource) Update(ctx context.Context, configID string, body map[string]any) (any, error)

func (*EmailConfigsResource) Verify

func (r *EmailConfigsResource) Verify(ctx context.Context, configID string, body map[string]any) (any, error)

type EmailLogOptions

type EmailLogOptions struct {
	ConfigID, Status, EventType, FromDate, ToDate string
	Page, Limit                                   int
}

type EmailLogsResource

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

func (*EmailLogsResource) List

func (r *EmailLogsResource) List(ctx context.Context, options EmailLogOptions) (any, error)

func (*EmailLogsResource) Stats

func (r *EmailLogsResource) Stats(ctx context.Context, options EmailLogOptions) (any, error)

type EmailSuppressionsResource

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

func (*EmailSuppressionsResource) List

func (*EmailSuppressionsResource) Remove

func (r *EmailSuppressionsResource) Remove(ctx context.Context, email string) (any, error)

type KeysResource

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

func (*KeysResource) Destroy

func (r *KeysResource) Destroy(ctx context.Context, keyID string) (any, error)

func (*KeysResource) Generate

func (r *KeysResource) Generate(ctx context.Context, name string) (any, error)

func (*KeysResource) List

func (r *KeysResource) List(ctx context.Context) (any, error)

func (*KeysResource) Reveal

func (r *KeysResource) Reveal(ctx context.Context, keyID string, confirmation map[string]any) (any, error)

func (*KeysResource) Rotate

func (r *KeysResource) Rotate(ctx context.Context, keyID string) (any, error)

type PaymentProfileResource

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

func (*PaymentProfileResource) Get

func (*PaymentProfileResource) RevealReturnSecret

func (r *PaymentProfileResource) RevealReturnSecret(ctx context.Context, confirmation map[string]any) (any, error)

func (*PaymentProfileResource) RotateReturnSecret

func (r *PaymentProfileResource) RotateReturnSecret(ctx context.Context) (any, error)

func (*PaymentProfileResource) Set

func (r *PaymentProfileResource) Set(ctx context.Context, body map[string]any) (any, error)

type QRResource

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

func (*QRResource) Cancel

func (r *QRResource) Cancel(ctx context.Context, qrCodeID string, body map[string]any) (any, error)

func (*QRResource) Generate

func (r *QRResource) Generate(ctx context.Context, body map[string]any) (any, error)

type SandboxResource

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

func (*SandboxResource) CreateTransaction

func (r *SandboxResource) CreateTransaction(ctx context.Context, body map[string]any) (any, error)

type TransactionIterator

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

TransactionIterator lazily retrieves transaction pages. Value is valid after Next returns true.

func (*TransactionIterator) Err

func (i *TransactionIterator) Err() error

func (*TransactionIterator) Next

func (i *TransactionIterator) Next() bool

func (*TransactionIterator) Value

func (i *TransactionIterator) Value() any

type TransactionOptions

type TransactionOptions struct {
	Page    int
	Limit   int
	SinceID string
}

type TransactionsResource

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

func (*TransactionsResource) Iterate

func (r *TransactionsResource) Iterate(ctx context.Context, virtualAccountNumber string, options TransactionOptions) *TransactionIterator

func (*TransactionsResource) List

func (r *TransactionsResource) List(ctx context.Context, virtualAccountNumber string, options TransactionOptions) (any, error)

func (*TransactionsResource) Retry

func (r *TransactionsResource) Retry(ctx context.Context, transactionID, targetType, targetID string) (any, error)

type VirtualAccountsResource

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

func (*VirtualAccountsResource) List

func (r *VirtualAccountsResource) List(ctx context.Context, bankAccountID string) (any, error)

func (*VirtualAccountsResource) Register

func (r *VirtualAccountsResource) Register(ctx context.Context, body map[string]any) (any, error)

func (*VirtualAccountsResource) RegisterNotification

func (r *VirtualAccountsResource) RegisterNotification(ctx context.Context, vaID string, body map[string]any) (any, error)

func (*VirtualAccountsResource) Verify

func (r *VirtualAccountsResource) Verify(ctx context.Context, requestID, code string) (any, error)

func (*VirtualAccountsResource) VerifyNotification

func (r *VirtualAccountsResource) VerifyNotification(ctx context.Context, requestID, code string) (any, error)

type WebhookLogOptions

type WebhookLogOptions struct {
	Status   string
	FromDate string
	ToDate   string
	Page     int
	Limit    int
}

type WebhookLogsResource

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

func (*WebhookLogsResource) List

func (r *WebhookLogsResource) List(ctx context.Context, options WebhookLogOptions) (any, error)

func (*WebhookLogsResource) Stats

func (r *WebhookLogsResource) Stats(ctx context.Context, options WebhookLogOptions) (any, error)

type WebhookResult

type WebhookResult struct {
	OK      bool
	Reason  string
	Payload any
}

func VerifyWebhook

func VerifyWebhook(rawBody []byte, timestamp, signature, secret string, toleranceSeconds ...int) (WebhookResult, error)

VerifyWebhook checks timestamp + HMAC against the exact request bytes and parses JSON. toleranceSeconds defaults to 300 when omitted.

type WebhooksResource

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

func (*WebhooksResource) Create

func (r *WebhooksResource) Create(ctx context.Context, body map[string]any) (any, error)

func (*WebhooksResource) List

func (r *WebhooksResource) List(ctx context.Context) (any, error)

func (*WebhooksResource) Remove

func (r *WebhooksResource) Remove(ctx context.Context, configID string) (any, error)

func (*WebhooksResource) Test

func (r *WebhooksResource) Test(ctx context.Context, body map[string]any) (any, error)

func (*WebhooksResource) Update

func (r *WebhooksResource) Update(ctx context.Context, configID string, body map[string]any) (any, error)

Directories

Path Synopsis
examples
webhook command

Jump to

Keyboard shortcuts

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