Back to Work
Library Open Source

Paytree

Ruby gem for M-Pesa Daraja API integration. Clean interface for STK Push, B2C disbursements, C2B collections, and transaction queries.

The Problem

M-Pesa integration is painful. The Daraja API documentation is dense, OAuth token management is tedious, error responses are inconsistent, and every project reinvents the wheel. Developers spend days on integration instead of building features.

The Solution

A Ruby gem that makes M-Pesa integration straightforward.

# Configure once
Paytree.configure do |config|
config.consumer_key = ENV["MPESA_CONSUMER_KEY"]
config.consumer_secret = ENV["MPESA_CONSUMER_SECRET"]
config.shortcode = ENV["MPESA_SHORTCODE"]
config.passkey = ENV["MPESA_PASSKEY"]
config.environment = :production
end
# STK Push (Lipa na M-Pesa)
result = Paytree.stk_push(
phone: "254712345678",
amount: 100,
reference: "ORDER-123",
description: "Payment for order"
)
# B2C Disbursement
result = Paytree.b2c(
phone: "254712345678",
amount: 500,
command: "BusinessPayment",
remarks: "Salary payment"
)

Features

STK Push

  • Initiate payments from customer phones
  • Callback URL configuration
  • Transaction status polling

B2C Payments

  • BusinessPayment, SalaryPayment, PromotionPayment commands
  • Bulk disbursement support
  • Automatic retry on timeout

C2B Registration

  • Register confirmation and validation URLs
  • Paybill and Till number support

Transaction Queries

  • Check transaction status by ID
  • Account balance inquiries
  • Transaction reversal

Developer Experience

  • Automatic OAuth token management and refresh
  • Meaningful error messages with Daraja error codes
  • Test mode with sandbox credentials
  • Comprehensive logging for debugging

Technical Details

Built on Faraday for HTTP with automatic retries on network failures. Token caching prevents unnecessary OAuth calls. Thread-safe for use in multi-threaded servers like Puma.

Response objects provide easy access to success/failure status, transaction IDs, and error details. No more parsing nested JSON manually.

if result.success?
puts result.transaction_id
else
puts result.error_message
puts result.error_code
end

Language: Ruby

Dependencies: Faraday, JSON

Compatibility: Ruby 3.0+, Rails 6+

License: MIT