ghion

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 22, 2026 License: MIT Imports: 3 Imported by: 0

README

github.com/yayawallet/ghion-go-sdk

A type-safe Go SDK for the Ghion Finances payment gateway. Built with security, maintainability, and scalability in mind for developers maintaining or contributing to this repository.

Features

  • Type-Safe: Full Go type definitions with comprehensive structs
  • Secure: HMAC-SHA256 authentication with timing-safe signature verification
  • Robust: Comprehensive error handling with custom error types
  • Validated: Built-in input validation for all API requests
  • Webhook Support: Secure webhook signature verification and parsing
  • Modern: Built with modern Go best practices
  • Multi-Channel: Support for USSD, QR, and OTP payment methods
  • Retry Logic: Automatic retry for transient failures and rate limits
  • Bill Payment API: Complete support for creating and managing bills
  • Auto-Generated Bill IDs: Support for optional BillID with auto-generation
  • Payment Reminders: Send payment reminders to customers via email and SMS
  • Checkout Initiation: Programmatically generate payment links for bills

Repository Structure

ghion-go-sdk/
├── ghion.go              # Main entry point and public API aliases
├── pkg/
│   ├── client/           # HTTP client and API methods
│   ├── types/            # Type definitions and structs
│   ├── errors/           # Custom error types
│   ├── utils/            # Utility functions (crypto, validation)
│   └── webhook/          # Webhook handling
├── examples/             # Usage examples (HTTP server, OTP, QR, Payment Lifecycle)
└── tests/                # Test files (unit and integration)

Setup for Development

1. Prerequisites
  • Go 1.19 or higher
  • Git
2. Clone the Repository
git clone https://github.com/yayawallet/ghion-go-sdk.git
cd ghion-go-sdk
3. Install Dependencies
go mod tidy

Adding New Features

1. Adding a New API Endpoint
  1. Define the types in pkg/types/types.go (Requests, Responses, Enums).
  2. Add validation in pkg/utils/validator.go if necessary.
  3. Implement the method in pkg/client/client.go using the generic apiRequest method.
  4. Export the types/methods in ghion.go via aliases.
  5. Add unit tests in pkg/client/client_test.go.
  6. Add integration tests in tests/integration_test.go (if applicable).
2. Adding a New Error Type
  1. Define the error in pkg/errors/errors.go.
  2. Export the error in ghion.go.
  3. Add tests in pkg/errors/errors_test.go.

Testing the SDK

Running All Tests

Run all tests across the SDK (unit tests only):

go test ./... -v
Running Package-Specific Tests

Run tests for specific packages:

# Client tests
go test ./pkg/client -v

# Utils tests (crypto, validation)
go test ./pkg/utils -v

# Error handling tests
go test ./pkg/errors -v

# Webhook tests
go test ./pkg/webhook -v
Test Coverage

Generate a test coverage report:

go test ./pkg/... -coverprofile=coverage.out -covermode=atomic

View coverage summary:

go tool cover -func=coverage.out

Generate HTML coverage report:

go tool cover -html=coverage.out

Current Coverage:

  • pkg/client: 72.4% (validation and configuration logic)
  • pkg/errors: 95.8% (error type constructors)
  • pkg/utils: 87.6% (crypto and validation functions)
  • pkg/webhook: 97.5% (signature verification and parsing)
Unit Tests (No Credentials Required)

Unit tests verify SDK logic without making API calls:

  • Client configuration and instantiation
  • Input validation functions
  • Cryptographic signature generation
  • Webhook signature verification
  • Error type constructors
  • Helper functions

Run unit tests:

go test ./pkg/... -v
Integration Tests (Credentials Required)

Integration tests make real API calls to verify SDK functionality with the Ghion API.

Setup:

  1. Create a .env file in the project root:
GHION_API_KEY=your_api_key
GHION_API_SECRET=your_api_secret
GHION_API_PASSPHRASE=your_passphrase
TEST_PHONE_NUMBER=+251911234567
TEST_OTP_CODE=123456  # For OTP validation test
  1. Install the godotenv package for loading environment variables:
go get github.com/joho/godotenv
  1. Run integration tests:
go test ./tests/ -v -tags=integration

Integration Test Coverage:

  • Initialize Payment: Tests payment initialization and channel availability
  • QR Payment: Tests QR code generation and checkout retrieval
  • OTP Payment: Tests OTP sending and validation (requires phone number)
  • YaYa Wallet Payment: Tests YaYa Wallet USSD payment flow
  • Telebirr Payment: Tests Telebirr USSD payment flow
  • USSD Payment: Tests generic USSD payment flow
  • Payment Status: Tests payment status retrieval
  • Get Checkout: Tests checkout details and available channels

Available Payment Channels:

  • YaYa Wallet (yayawallet)
  • Card (card)
  • Telebirr (telebirr)
  • CBE Birr (cbebirr)
  • M-PESA (mpesa)
  • Kacha (kacha)
  • CBE Mobile (cbemobile)
  • Awash Birr (awashbirr)
  • Hijra Bank (hijirabank)
  • Ahadu (ahadu)
  • NIB Bank (NIB)

Test Organization:

  • Unit tests are located in pkg/*/ directories alongside source code
  • Integration tests are located in tests/ directory with // +build integration tag
  • Tests are organized by package for accurate coverage reporting
Writing Tests

Tests are organized by package in the pkg/ directory:

Test Structure:

package client

import (
    "testing"
    "github.com/yayawallet/ghion-go-sdk/pkg/types"
)

func TestNewGhionClient(t *testing.T) {
    tests := []struct {
        name        string
        config      *types.GhionConfig
        expectError bool
    }{
        {
            name: "valid config",
            config: &types.GhionConfig{
                APIKey:     "test-key",
                APISecret:  "test-secret",
                Passphrase: "test-passphrase",
            },
            expectError: false,
        },
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            client, err := NewGhionClient(tt.config)
            if tt.expectError && err == nil {
                t.Error("Expected error but got none")
            }
            if !tt.expectError && err != nil {
                t.Errorf("Expected no error but got: %v", err)
            }
            if !tt.expectError && client == nil {
                t.Error("Expected client but got nil")
            }
        })
    }
}

Testing Guidelines:

  • Use table-driven tests for multiple test cases
  • Test both success and error paths
  • Validate error types when expecting errors
  • Test edge cases (empty strings, zero values, invalid inputs)
  • Mock external dependencies when possible
  • Keep tests independent and deterministic
Running Examples

See the examples/ directory for complete working scripts:

# Basic quick start example
go run examples/quick-start.go

# Comprehensive payment lifecycle test
go run examples/payment-lifecycle.go

# HTTP server with webhook handling
go run examples/http-server.go

# OTP flow example
go run examples/otp-flow.go
CI/CD Testing

For continuous integration, run:

# Run all tests with coverage
go test ./... -coverprofile=coverage.out -covermode=atomic

# Check coverage threshold (e.g., 70%)
go tool cover -func=coverage.out | grep total

Code Quality & Guidelines

  • Style: Use gofmt to format code before committing (go fmt ./...).
  • Linting: We recommend using golangci-lint to ensure code quality.
  • Documentation: All exported functions, types, and constants must have proper Go doc comments.
  • Error Handling: Use the custom error types in pkg/errors instead of generic Go errors. Never expose sensitive information in error messages. Redact sensitive data from logs.

Security Considerations

  • HMAC-SHA256 Authentication: All API requests are signed using HMAC-SHA256.
  • Timing-Safe Comparison: Webhook signatures use constant-time comparison (subtle.ConstantTimeCompare) to prevent timing attacks.
  • Input Validation: All inputs are validated before being sent over the network.
  • Sensitive Data Redaction: Error responses automatically redact sensitive information (API keys, passphrases, signatures).

Contributing

Contributions are welcome! Please ensure:

  1. Code adheres to existing style (go fmt).
  2. All tests pass (go test ./...).
  3. Documentation is updated.
  4. Changes are backwards compatible when possible.

Please open an issue to discuss proposed changes before creating a pull request.

For release guidelines, see RELEASE.md.

License

See LICENSE file for details.

Documentation

Overview

Package ghion is the Go SDK for Ghion Finances payment gateway

This SDK provides a simple and secure way to integrate Ghion Finances payment gateway into your Go applications. It supports multiple payment channels including USSD, QR, OTP, and provides comprehensive webhook handling.

Quick Start:

client, err := ghion.NewClient(&ghion.Config{
    APIKey:     "your-api-key",
    APISecret:  "your-api-secret",
    Passphrase: "your-passphrase",
})
if err != nil {
    log.Fatal(err)
}

payment, err := client.InitializePayment(&ghion.InitializePaymentRequest{
    Amount:    100,
    Reference: "order_12345",
})
if err != nil {
    log.Fatal(err)
}

fmt.Printf("Payment initialized: %s\n", payment.ID)

Index

Constants

View Source
const (
	// PaymentStatusPending represents a pending payment
	PaymentStatusPending = types.PaymentStatusPending
	// PaymentStatusProcessing represents a processing payment
	PaymentStatusProcessing = types.PaymentStatusProcessing
	// PaymentStatusCompleted represents a completed payment
	PaymentStatusCompleted = types.PaymentStatusCompleted
	// PaymentStatusFailed represents a failed payment
	PaymentStatusFailed = types.PaymentStatusFailed
	// PaymentStatusCancelled represents a cancelled payment
	PaymentStatusCancelled = types.PaymentStatusCancelled
	// PaymentStatusExpired represents an expired payment
	PaymentStatusExpired = types.PaymentStatusExpired
)
View Source
const (
	// StatusPending is a shorter alias for PaymentStatusPending
	StatusPending = types.PaymentStatusPending
	// StatusProcessing is a shorter alias for PaymentStatusProcessing
	StatusProcessing = types.PaymentStatusProcessing
	// StatusCompleted is a shorter alias for PaymentStatusCompleted
	StatusCompleted = types.PaymentStatusCompleted
	// StatusFailed is a shorter alias for PaymentStatusFailed
	StatusFailed = types.PaymentStatusFailed
	// StatusCancelled is a shorter alias for PaymentStatusCancelled
	StatusCancelled = types.PaymentStatusCancelled
	// StatusExpired is a shorter alias for PaymentStatusExpired
	StatusExpired = types.PaymentStatusExpired
)

Shorter aliases for payment status (status.something format)

View Source
const (
	// EventTransactionCompleted represents a transaction completed event
	EventTransactionCompleted = types.EventTransactionCompleted
	// EventTransactionFailed represents a transaction failed event
	EventTransactionFailed = types.EventTransactionFailed
	// EventTransactionRefunded represents a transaction refunded event
	EventTransactionRefunded = types.EventTransactionRefunded
	// EventTransactionPartiallyRefunded represents a transaction partially refunded event
	EventTransactionPartiallyRefunded = types.EventTransactionPartiallyRefunded
	// EventTransactionExpired represents a transaction expired event
	EventTransactionExpired = types.EventTransactionExpired
	// EventTransactionDisputed represents a transaction disputed event
	EventTransactionDisputed = types.EventTransactionDisputed
	// EventTransactionUpdated represents a transaction updated event
	EventTransactionUpdated = types.EventTransactionUpdated
)

Variables

View Source
var (
	// NewConfigurationError creates a new ConfigurationError
	NewConfigurationError = errors.NewConfigurationError
	// NewAuthenticationError creates a new AuthenticationError
	NewAuthenticationError = errors.NewAuthenticationError
	// NewAPIError creates a new APIError
	NewAPIError = errors.NewAPIError
	// NewValidationError creates a new ValidationError
	NewValidationError = errors.NewValidationError
	// NewNetworkError creates a new NetworkError
	NewNetworkError = errors.NewNetworkError
	// NewPaymentError creates a new PaymentError
	NewPaymentError = errors.NewPaymentError
	// NewBillError creates a new BillError
	NewBillError = errors.NewBillError
	// NewWebhookError creates a new WebhookError
	NewWebhookError = errors.NewWebhookError
	// NewRateLimitError creates a new RateLimitError
	NewRateLimitError = errors.NewRateLimitError
)

Error constructors

Functions

This section is empty.

Types

type APIError added in v1.1.0

type APIError = errors.APIError

APIError represents a failed HTTP request

type AuthenticationError added in v1.1.0

type AuthenticationError = errors.AuthenticationError

AuthenticationError represents invalid credentials or signature

type BillError added in v1.1.0

type BillError = errors.BillError

BillError represents bill processing failures

type CheckoutResponse

type CheckoutResponse = types.CheckoutResponse

CheckoutResponse represents checkout information

type Client

type Client = client.GhionClient

Client is the main SDK client for Ghion Finances payment gateway

func NewClient

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

NewClient creates a new Ghion client with the given configuration

type Config

type Config = types.GhionConfig

Config represents the configuration for the Ghion client

type ConfigurationError added in v1.1.0

type ConfigurationError = errors.ConfigurationError

ConfigurationError represents invalid SDK configuration

type Customer

type Customer = types.Customer

Customer represents customer information

type GhionError added in v1.1.0

type GhionError = errors.GhionError

GhionError is the base error class for all SDK errors

type InitializePaymentRequest

type InitializePaymentRequest = types.InitializePaymentRequest

InitializePaymentRequest represents a payment initialization request

type InitializePaymentResponse

type InitializePaymentResponse = types.InitializePaymentResponse

InitializePaymentResponse represents a payment initialization response

type Merchant

type Merchant = types.Merchant

Merchant represents merchant information

type NetworkError added in v1.1.0

type NetworkError = errors.NetworkError

NetworkError represents connection or timeout issues

type OTPSendResponse

type OTPSendResponse = types.OTPSendResponse

OTPSendResponse represents an OTP send response

type OTPValidateResponse

type OTPValidateResponse = types.OTPValidateResponse

OTPValidateResponse represents an OTP validation response

type PaymentChannel

type PaymentChannel = types.PaymentChannel

PaymentChannel represents an available payment channel

type PaymentError added in v1.1.0

type PaymentError = errors.PaymentError

PaymentError represents payment processing failures

type PaymentStatus

type PaymentStatus = types.PaymentStatus

PaymentStatus represents the status of a payment

type PaymentStatusResponse

type PaymentStatusResponse = types.PaymentStatusResponse

PaymentStatusResponse represents a payment status response

type Provider

type Provider = types.Provider

Provider represents payment provider information

type QRInfo

type QRInfo = types.QRInfo

QRInfo represents QR code information

type QRPaymentResponse

type QRPaymentResponse = types.QRPaymentResponse

QRPaymentResponse represents a QR payment response

type RateLimitError added in v1.1.0

type RateLimitError = errors.RateLimitError

RateLimitError represents API rate limit exceeded

type SubmitPaymentRequest

type SubmitPaymentRequest = types.SubmitPaymentRequest

SubmitPaymentRequest represents a payment submission request

type SubmitPaymentResponse

type SubmitPaymentResponse = types.SubmitPaymentResponse

SubmitPaymentResponse represents a payment submission response

type ValidationError added in v1.1.0

type ValidationError = errors.ValidationError

ValidationError represents invalid input parameters

type WebhookError added in v1.1.0

type WebhookError = errors.WebhookError

WebhookError represents webhook signature verification or processing failures

type WebhookEvent

type WebhookEvent = types.WebhookEvent

WebhookEvent represents a webhook event payload

type WebhookEventType

type WebhookEventType = types.WebhookEventType

WebhookEventType represents the type of webhook event

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

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