A comprehensive Go SDK for integrating MTN Mobile Money (MoMo) payment services into your applications. This SDK provides simple, idiomatic Go interfaces to MTN's collection, disbursement, account, and refund APIs.
- Collections API: Request payments from customers
- Disbursements API: Send money to customers
- Account API: Check balance and validate account holders
- Refunds API: Handle transaction refunds
- Type-safe: Fully typed request/response structures
- Error handling: Comprehensive error handling and validation
- Idempotent requests: Built-in support for idempotent operations
- Zero external dependencies: Uses only Go standard library
go get github.com/Bahatiroben/mtn-momo-sdk-gopackage main
import (
"log"
"time"
"github.com/Bahatiroben/mtn-momo-sdk-go/pgk/momo"
)
func main() {
config := &momo.Config{
BaseURL: "https://sandbox.momodeveloper.mtn.com",
APIKey: "your-api-key",
PrimaryKey: "your-primary-key",
SecondaryKey: "your-secondary-key",
SubscriptionKey: "your-subscription-key",
Timeout: 30 * time.Second,
}
sdk, err := momo.NewSDK(config)
if err != nil {
log.Fatalf("Failed to initialize SDK: %v", err)
}
defer sdk.Close()
}req := &momo.CollectionRequest{
Amount: momo.Money{
Amount: "1000",
Currency: "RWF",
},
Currency: "RWF",
ExternalId: "txn-unique-id-123",
Payer: momo.Party{
PartyIdType: momo.PartyIdTypeMSISDN,
PartyId: "250780000000",
PartyName: "John Doe",
},
PayerMessage: "Payment for goods",
PayeeNote: "Invoice #2024001",
}
resp, err := sdk.Collections.RequestToPay(req)
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Transaction ID: %s", resp.TransactionId)status, err := sdk.Collections.GetTransactionStatus("txn-unique-id-123")
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Status: %s", status.Status)req := &momo.DisbursementRequest{
Amount: momo.Money{
Amount: "2000",
Currency: "RWF",
},
Currency: "RWF",
ExternalId: "transfer-unique-id",
Payee: momo.Party{
PartyIdType: momo.PartyIdTypeMSISDN,
PartyId: "250780000000",
PartyName: "Jane Smith",
},
PayerMessage: "Salary payment",
PayeeNote: "Monthly salary",
}
resp, err := sdk.Disbursements.Transfer(req)
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Transfer initiated with ID: %s", resp.TransactionId)balance, err := sdk.Account.GetBalance("RWF")
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Balance: %s %s", balance.Balance, balance.Currency)info, err := sdk.Account.ValidateAccountHolder("250780000000", momo.PartyIdTypeMSISDN)
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Account validation result: %s", info.Result)req := &momo.RefundRequest{
Amount: momo.Money{
Amount: "1000",
Currency: "RWF",
},
Currency: "RWF",
ExternalId: "refund-001",
OriginalTransactionId: "txn-unique-id-123",
Reason: "Customer requested refund",
}
resp, err := sdk.Refunds.CreateRefund(req)
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Refund created with ID: %s", resp.TransactionId)Initiates a request for payment from a customer.
func (c *Collections) RequestToPay(req *CollectionRequest) (*CollectionResponse, error)Convenience method with flexible options.
func (c *Collections) RequestToPayWithOptions(
amount, currency, externalId, payerId string,
additionalOptions map[string]interface{},
) (*CollectionResponse, error)Checks the status of a collection request.
func (c *Collections) GetTransactionStatus(transactionId string) (*TransactionStatusResponse, error)Initiates a disbursement/transfer to a customer.
func (d *Disbursements) Transfer(req *DisbursementRequest) (*DisbursementResponse, error)Convenience method with flexible options.
func (d *Disbursements) TransferWithOptions(
amount, currency, externalId, payeeId string,
additionalOptions map[string]interface{},
) (*DisbursementResponse, error)Checks the status of a disbursement.
func (d *Disbursements) GetTransactionStatus(transactionId string) (*TransactionStatusResponse, error)Retrieves the current account balance.
func (a *Account) GetBalance(currency string) (*BalanceResponse, error)Checks if an account holder exists.
func (a *Account) ValidateAccountHolder(
accountHolderId, accountHolderIdType string,
) (*AccountHolderResponse, error)Retrieves account information.
func (a *Account) GetAccountInfo(accountId string) (*AccountHolderResponse, error)Initiates a refund for a previous transaction.
func (r *Refunds) CreateRefund(req *RefundRequest) (*RefundResponse, error)Convenience method with flexible options.
func (r *Refunds) CreateRefundWithOptions(
amount, currency, externalId, originalTransactionId string,
additionalOptions map[string]interface{},
) (*RefundResponse, error)Checks the status of a refund request.
func (r *Refunds) GetRefundStatus(transactionId string) (*TransactionStatusResponse, error)Configuration for the SDK client.
type Config struct {
BaseURL string // API base URL
APIKey string // API key
PrimaryKey string // Primary key
SecondaryKey string // Secondary key
SubscriptionKey string // Subscription key
Timeout time.Duration // Request timeout
}Represents a party in a transaction (payer or payee).
type Party struct {
PartyIdType string // MSISDN, EMAIL, or PARTY_CODE
PartyId string // Phone number or email
PartyName string // Optional name
}Represents a monetary amount.
type Money struct {
Amount string // Amount in smallest currency unit
Currency string // ISO 4217 currency code
}The SDK returns detailed error messages for failed requests:
resp, err := sdk.Collections.RequestToPay(req)
if err != nil {
// Handle error
log.Printf("Failed to request payment: %v", err)
}Common errors include:
- Invalid configuration parameters
- Missing required fields in requests
- API authentication failures
- Network timeouts
- Invalid currency codes
-
Use ExternalId for Idempotency: Always provide a unique
ExternalIdfor each request to ensure idempotent operations. This prevents duplicate transactions if a request is retried. -
Check Transaction Status: Always check transaction status after receiving a response, as the immediate response doesn't guarantee completion.
-
Handle Timeouts: Configure appropriate timeout values based on your use case. Default is 30 seconds.
-
Validate Parties: Use
ValidateAccountHolderbefore initiating transactions to ensure the recipient exists. -
Log Transactions: Keep logs of all transaction IDs for reconciliation and audit purposes.
-
Use Sandbox for Testing: Develop and test against the sandbox environment before moving to production.
PartyIdTypeMSISDN: Mobile numberPartyIdTypeEmail: Email addressPartyIdTypePartyCode: Party code
TransactionStatusSuccessful: Transaction completed successfullyTransactionStatusFailed: Transaction failedTransactionStatusPending: Transaction is pending
TransactionTypeCashin: Cash-in transactionTransactionTypeCashout: Cash-out transactionTransactionTypeTransfer: Transfer transactionTransactionTypeBillPayment: Bill paymentTransactionTypeRefund: Refund transaction
go test ./...Contributions are welcome! Please ensure:
- Code follows Go conventions
- Tests are included for new features
- Documentation is updated
- No external dependencies are added without good reason
This SDK is provided as-is for integration with MTN Mobile Money services.
For issues, questions, or suggestions:
- Check the examples directory for usage patterns
- Review the API documentation from MTN Developer Portal
- Ensure your credentials are correct and have appropriate permissions
- Initial release
- Collections API
- Disbursements API
- Account API
- Refunds API
- Comprehensive test coverage
- Full documentation