Yimaru-BackEnd/docs/ARIFPAY_INTEGRATION.md

8.1 KiB

ArifPay Payment Gateway Integration

This document describes the ArifPay payment gateway integration for subscription payments in the Yimaru LMS application.

Overview

The integration coordinates payment with subscriptions - users cannot create subscriptions without completing payment. Only admins can bypass this restriction for special cases (e.g., promotional subscriptions).

Key Features:

  • Payment-first approach: Subscriptions are only created after successful payment
  • Multiple payment flows: Checkout redirect or direct OTP-based payment
  • Webhook handling: Automatic subscription creation on payment success
  • Role-based access: Regular users must pay; admins can grant free subscriptions

The integration supports multiple Ethiopian payment methods including:

  • Telebirr
  • CBE (Commercial Bank of Ethiopia)
  • Awash Bank
  • Amole
  • HelloCash
  • M-Pesa
  • And more

Environment Variables

Add the following environment variables to your .env file:

# ArifPay Configuration
ARIFPAY_API_KEY=your_arifpay_api_key
ARIFPAY_BASE_URL=https://gateway.arifpay.net
ARIFPAY_CANCEL_URL=https://yourdomain.com/payment/cancelled
ARIFPAY_SUCCESS_URL=https://yourdomain.com/payment/success
ARIFPAY_ERROR_URL=https://yourdomain.com/payment/error
ARIFPAY_C2B_NOTIFY_URL=https://yourdomain.com/api/v1/payments/webhook
ARIFPAY_B2C_NOTIFY_URL=https://yourdomain.com/api/v1/payments/b2c-webhook
ARIFPAY_BANK=AWINETAA
ARIFPAY_BENEFICIARY_ACCOUNT_NUMBER=your_account_number
ARIFPAY_DESCRIPTION=Yimaru LMS Subscription
ARIFPAY_ITEM_NAME=Subscription

Database Migration

Run the migration to create the payments table:

migrate -path db/migrations -database "postgres://..." up

Or manually run:

-- See db/migrations/000009_payments.up.sql

API Endpoints

Subscription Endpoints

POST /api/v1/subscriptions/checkout

The primary endpoint for users to subscribe. Initiates payment and returns checkout URL.

Request Body:

{
  "plan_id": 1,
  "phone": "0912345678",
  "email": "user@example.com"
}

Response:

{
  "message": "Payment initiated. Complete payment to activate subscription.",
  "data": {
    "payment_id": 123,
    "session_id": "ABC123DEF456",
    "payment_url": "https://checkout.arifpay.net/...",
    "amount": 299.99,
    "currency": "ETB",
    "expires_at": "2024-01-15T18:30:00Z"
  }
}

Direct Subscribe (Admin Only)

POST /api/v1/subscriptions

Creates subscription without payment. Only accessible by admin/super_admin roles.


Payment Endpoints

Initiate Subscription Payment

POST /api/v1/payments/subscribe

Creates a payment session for a subscription plan.

Request Body:

{
  "plan_id": 1,
  "phone": "0912345678",
  "email": "user@example.com"
}

Response:

{
  "message": "Payment initiated successfully",
  "data": {
    "payment_id": 123,
    "session_id": "ABC123DEF456",
    "payment_url": "https://checkout.arifpay.net/...",
    "amount": 299.99,
    "currency": "ETB",
    "expires_at": "2024-01-15T18:30:00Z"
  }
}

Verify Payment Status

GET /api/v1/payments/verify/:session_id

Checks the payment status with ArifPay and updates local records.

Response:

{
  "message": "Payment status retrieved",
  "data": {
    "id": 123,
    "status": "SUCCESS",
    "subscription_id": 456,
    ...
  }
}

Get Payment History

GET /api/v1/payments

Returns the authenticated user's payment history.

Query Parameters:

  • limit (default: 20)
  • offset (default: 0)

Get Payment Details

GET /api/v1/payments/:id

Returns details of a specific payment.

Cancel Payment

POST /api/v1/payments/:id/cancel

Cancels a pending payment.

Payment Webhook

POST /api/v1/payments/webhook

Webhook endpoint called by ArifPay when payment status changes.

Note: This endpoint does not require authentication as it's called by ArifPay servers.

Get Available Payment Methods

GET /api/v1/payments/methods

Returns list of supported payment methods.


Direct Payment Endpoints (OTP-based)

Direct payments allow users to pay without being redirected to a payment page. Instead, the payment is processed via OTP verification.

Initiate Direct Payment

POST /api/v1/payments/direct

Initiates a direct payment with a specific payment method.

Request Body:

{
  "plan_id": 1,
  "phone": "0912345678",
  "email": "user@example.com",
  "payment_method": "AMOLE"
}

Supported Payment Methods:

  • TELEBIRR - Telebirr (push notification)
  • TELEBIRR_USSD - Telebirr USSD
  • CBE - Commercial Bank of Ethiopia
  • AMOLE - Amole (requires OTP)
  • HELLOCASH - HelloCash (requires OTP)
  • AWASH - Awash Bank (requires OTP)
  • MPESA - M-Pesa

Response:

{
  "message": "OTP sent to your phone. Please verify to complete payment.",
  "data": {
    "payment_id": 123,
    "session_id": "ABC123DEF456",
    "requires_otp": true,
    "amount": 299.99,
    "currency": "ETB"
  }
}

Verify OTP

POST /api/v1/payments/direct/verify-otp

Verifies the OTP for direct payment methods (Amole, HelloCash, Awash).

Request Body:

{
  "session_id": "ABC123DEF456",
  "otp": "123456"
}

Response (Success):

{
  "message": "Payment completed successfully",
  "data": {
    "success": true,
    "transaction_id": "TXN123456",
    "payment_id": 123
  }
}

Response (Failed):

{
  "message": "Invalid OTP"
}

Get Direct Payment Methods

GET /api/v1/payments/direct/methods

Returns list of payment methods that support direct payment.


Payment Flows

Flow 1: Checkout Session (Redirect-based)

  1. User selects a subscription plan and initiates payment via /payments/subscribe
  2. Backend creates a payment record with status PENDING
  3. Backend calls ArifPay to create a checkout session
  4. User is redirected to ArifPay payment page (using payment_url)
  5. User completes payment on ArifPay
  6. ArifPay sends webhook to notify payment status
  7. Backend processes webhook:
    • Updates payment status
    • If successful, creates subscription
    • Links payment to subscription
  8. User can verify payment status via /payments/verify/:session_id

Flow 2: Direct Payment (OTP-based)

  1. User selects plan and payment method via /payments/direct
  2. Backend creates payment record and checkout session
  3. Backend initiates direct transfer with selected payment method
  4. For OTP-required methods (Amole, HelloCash, Awash):
    • User receives OTP via SMS
    • User submits OTP via /payments/direct/verify-otp
    • Backend verifies OTP with ArifPay
    • On success, creates subscription
  5. For push-based methods (Telebirr, CBE):
    • User receives push notification on their app
    • User approves payment in their app
    • ArifPay sends webhook notification
    • Backend creates subscription

Statuses

Payment Statuses

  • PENDING - Payment initiated, waiting for user action
  • PROCESSING - Payment is being processed
  • SUCCESS - Payment completed successfully
  • FAILED - Payment failed
  • CANCELLED - Payment cancelled by user
  • EXPIRED - Payment session expired

Subscription Statuses

  • PENDING - Subscription pending payment
  • ACTIVE - Subscription is active
  • EXPIRED - Subscription has expired
  • CANCELLED - Subscription was cancelled

Error Handling

The integration handles various error scenarios:

  • User already has an active subscription
  • Plan not found or inactive
  • Payment verification failures
  • Webhook processing errors

Security Considerations

  1. Webhook endpoint validates requests from ArifPay
  2. Payment verification double-checks with ArifPay API
  3. User can only access their own payment records
  4. Sensitive data (API keys) stored in environment variables

Testing

For sandbox testing, use:

  • Base URL: https://gateway.arifpay.net (sandbox mode enabled via API key)
  • Test phone numbers provided by ArifPay
  • Sandbox credentials from ArifPay developer portal

Support

For ArifPay-specific issues: