Sunny Payments Ruby

Sunny Payments Ruby SDK

The official Ruby SDK for Sunny Payments - Payment processing made simple.

Gem Version License: MIT

Installation

gem install sunny-payments

Or add to your Gemfile:

gem 'sunny-payments', '~> 1.0'

Quick Start

require 'sunny'

# Initialize the client
sunny = Sunny::Client.new('sk_live_your_api_key')

# Create a payment (currency is REQUIRED)
payment = sunny.payments.create(
  amount: 1000,
  currency: 'KES',  # Required - no default!
  source: 'mpesa',
  description: 'Order #12345'
)

puts payment['id']  # pay_xxxxx

Features

  • Payments - Create, capture, refund payments
  • Mobile Money - M-Pesa STK Push, B2C, MTN MoMo, Airtel Money
  • Invoices - Create and send invoices
  • Bills - Airtime, data, electricity payments
  • QR Codes - Static and dynamic QR payments
  • Crypto - Accept BTC, ETH, USDT, USDC
  • Webhooks - Register endpoints & verify signatures
  • BNPL - Buy Now Pay Later

Usage Examples

M-Pesa STK Push

result = sunny.mobile_money.mpesa_stk_push(
  phone_number: '254712345678',
  amount: 1000,
  currency: 'KES',  # Required
  account_reference: 'ORDER-001'
)

# Check status
status = sunny.mobile_money.mpesa_status(result['checkout_request_id'])

Bills

# Purchase airtime
sunny.bills.purchase_airtime(
  phone_number: '+254712345678',
  amount: 100,
  network: 'safaricom'
)

# Buy electricity tokens
electricity = sunny.bills.purchase_electricity(
  meter_number: '12345678',
  amount: 500,
  phone_number: '+254712345678'
)
puts electricity['token']  # KPLC token

Crypto Payments

address = sunny.crypto.create_address(
  cryptocurrency: 'USDT',
  amount: 10000,
  currency: 'KES'  # Required
)

Webhooks

# Register webhook
webhook = sunny.webhooks.create(
  url: 'https://example.com/webhooks/sunny',
  events: ['payment.succeeded', 'payment.failed']
)

# In your Sinatra/Rails controller:
post '/webhooks/sunny' do
  payload = request.body.read
  signature = request.env['HTTP_X_SUNNY_SIGNATURE']

  unless Sunny::Resources::Webhooks.verify_signature(payload, signature, WEBHOOK_SECRET)
    halt 400, 'Invalid signature'
  end

  event = JSON.parse(payload)

  case event['type']
  when 'payment.succeeded'
    # Handle successful payment
  end

  status 200
  'OK'
end

Error Handling

begin
  payment = sunny.payments.create(amount: 1000, currency: 'KES', source: 'mpesa')
rescue Sunny::AuthenticationError
  puts "Invalid API key"
rescue Sunny::ValidationError => e
  puts "Validation error: #{e.message}, field: #{e.field}"
rescue Sunny::RateLimitError => e
  puts "Rate limited. Retry after #{e.retry_after} seconds"
rescue Sunny::APIError => e
  puts "API error: #{e.message}"
end

Configuration

# Via environment variable
ENV['SUNNY_API_KEY'] = 'sk_live_xxx'

# Or configure directly
sunny = Sunny::Client.new('sk_live_xxx', {
  base_url: 'https://api.sunnypay.co.ke/v1',
  timeout: 30
})

License

MIT License - see LICENSE for details.