Skip to main content
The PaymentService handles payment-related operations, including mobile money account verification using Paystack integration.

Service Creation

import { createPaymentService } from '@/services/payment/payment.service';
import { httpClient } from '@/services/http.service';

const paymentService = createPaymentService(httpClient);
Source: src/services/payment/payment.service.ts:5-14

Methods

verifyMobileMoneyNumber

Verifies a mobile money account number with a provider to ensure it’s valid and retrieve the account holder’s name.
paymentService.verifyMobileMoneyNumber(
  accountNumber: string,
  provider: string
): ApiResponse<VerifyMobileMoneyResponse>

Parameters

accountNumber
string
required
The mobile money account number to verify. This is typically a phone number formatted according to the provider’s requirements.
provider
string
required
The mobile money provider code. Supported providers include:
  • mtn - MTN Mobile Money
  • orange - Orange Money
  • moov - Moov Money

Response

accountName
string
required
The verified account holder’s name as registered with the mobile money provider

Example Usage

import { paymentService } from '@/services';

try {
  const response = await paymentService.verifyMobileMoneyNumber(
    '237670000000',
    'mtn'
  );
  
  console.log('Account verified:', response.data.accountName);
  // Output: "Account verified: John Doe"
  
  // Use verified name to confirm with user
  const confirmed = await confirmAccountName(response.data.accountName);
  if (confirmed) {
    // Proceed with payout request
  }
} catch (error) {
  if (error.status === 422) {
    console.error('Invalid account number or provider');
  } else if (error.status === 404) {
    console.error('Account not found with provider');
  } else {
    console.error('Verification failed:', error.message);
  }
}

API Endpoint

The verification method calls the following endpoint:
POST /payment/verify-mobile-money-account
Source: src/services/api/end-points.ts:43-45

Request Body

{
  "accountNumber": "237670000000",
  "provider": "mtn"
}

Response Body

{
  "accountName": "John Doe"
}

Mobile Money Providers

The service supports verification for major mobile money operators in Cameroon:

MTN Mobile Money

  • Provider Code: mtn
  • Account Format: Phone number with country code (237XXXXXXXXX)
  • Coverage: Nationwide

Orange Money

  • Provider Code: orange
  • Account Format: Phone number with country code (237XXXXXXXXX)
  • Coverage: Nationwide

Moov Money

  • Provider Code: moov
  • Account Format: Phone number with country code (237XXXXXXXXX)
  • Coverage: Regional

Paystack Integration

The verification service is powered by Paystack’s Transfer Recipients API, which validates mobile money accounts in real-time.

How It Works

  1. The app submits account number and provider to the backend
  2. Backend forwards the request to Paystack API
  3. Paystack verifies the account with the mobile money operator
  4. Backend returns the verified account holder’s name
  5. User confirms the name matches their intended recipient

Type Definitions

VerifyMobileMoneyResponse

interface VerifyMobileMoneyResponse {
  accountName: string;
}
Source: src/types/payout.types.ts:34-36

Error Handling

The verification method can throw various errors:

422 - Validation Error

{
  "message": "Erreur de validation",
  "status": 422,
  "data": {
    "message": "Invalid account number format",
    "errors": [
      {
        "field": "accountNumber",
        "message": "Account number must be a valid phone number"
      }
    ]
  },
  "isApiError": true
}
Caused by:
  • Invalid account number format
  • Unsupported provider
  • Missing required parameters

404 - Account Not Found

{
  "message": "Ressource non trouvée",
  "status": 404,
  "data": {
    "message": "Account not found with the specified provider"
  },
  "isApiError": true
}
Caused by:
  • Account number doesn’t exist
  • Wrong provider specified
  • Account is inactive or closed

500 - Provider Service Error

{
  "message": "Erreur serveur: Veuillez réessayer plus tard",
  "status": 500,
  "isApiError": true
}
Caused by:
  • Paystack API is down
  • Mobile money provider service unavailable
  • Network timeout with provider

Use Cases

Payout Request Flow

Verify mobile money accounts before creating payout requests:
import { paymentService, usersService } from '@/services';

const requestPayout = async (
  amount: number,
  accountNumber: string,
  provider: string
) => {
  try {
    // Step 1: Verify the mobile money account
    const verification = await paymentService.verifyMobileMoneyNumber(
      accountNumber,
      provider
    );
    
    // Step 2: Show verified name to user for confirmation
    const confirmed = await showConfirmationDialog(
      `Le nom du compte est: ${verification.data.accountName}. Confirmer?`
    );
    
    if (!confirmed) {
      throw new Error('Payout cancelled by user');
    }
    
    // Step 3: Create the payout request
    const payout = await usersService.createPayoutRequest({
      amount,
      payoutMethod: 'mobile_money',
      mobileMoneyProvider: provider,
      mobileMoneyNumber: accountNumber,
      mobileMoneyAccountName: verification.data.accountName,
    });
    
    console.log('Payout request created:', payout.data.reference);
    return payout.data;
    
  } catch (error) {
    if (error.status === 404) {
      throw new Error('Numéro de compte invalide');
    } else if (error.status === 422) {
      throw new Error('Format de numéro incorrect');
    } else {
      throw new Error('Échec de la vérification du compte');
    }
  }
};

Form Validation

Integrate verification into payout forms:
import { useState } from 'react';
import { paymentService } from '@/services';

const PayoutForm = () => {
  const [accountNumber, setAccountNumber] = useState('');
  const [provider, setProvider] = useState('mtn');
  const [verifiedName, setVerifiedName] = useState<string | null>(null);
  const [isVerifying, setIsVerifying] = useState(false);
  const [error, setError] = useState<string | null>(null);
  
  const handleVerify = async () => {
    setIsVerifying(true);
    setError(null);
    
    try {
      const response = await paymentService.verifyMobileMoneyNumber(
        accountNumber,
        provider
      );
      
      setVerifiedName(response.data.accountName);
    } catch (err) {
      setError('Impossible de vérifier le numéro de compte');
      setVerifiedName(null);
    } finally {
      setIsVerifying(false);
    }
  };
  
  return (
    <View>
      <Input
        value={accountNumber}
        onChangeText={setAccountNumber}
        placeholder="Numéro de téléphone"
      />
      
      <Picker
        selectedValue={provider}
        onValueChange={setProvider}
      >
        <Picker.Item label="MTN Mobile Money" value="mtn" />
        <Picker.Item label="Orange Money" value="orange" />
        <Picker.Item label="Moov Money" value="moov" />
      </Picker>
      
      <Button
        title="Vérifier le compte"
        onPress={handleVerify}
        loading={isVerifying}
      />
      
      {verifiedName && (
        <Text style={{ color: 'green' }}>
          Nom du compte: {verifiedName}
        </Text>
      )}
      
      {error && (
        <Text style={{ color: 'red' }}>{error}</Text>
      )}
    </View>
  );
};

Best Practices

  • Always verify mobile money accounts before creating payouts
  • Display the verified account name to users for confirmation
  • Handle verification errors gracefully with user-friendly messages
  • Cache verification results to avoid redundant API calls
  • Implement retry logic for transient network errors
  • Validate account number format before calling the API
  • Never store sensitive payment information locally
  • Always use HTTPS for payment-related requests
  • Implement rate limiting to prevent abuse
  • Log verification attempts for audit purposes

Account Number Formatting

Ensure account numbers are properly formatted before verification:
const formatAccountNumber = (phoneNumber: string, countryCode: string = '237'): string => {
  // Remove spaces, dashes, and special characters
  let formatted = phoneNumber.replace(/[^0-9]/g, '');
  
  // Add country code if not present
  if (!formatted.startsWith(countryCode)) {
    formatted = countryCode + formatted;
  }
  
  return formatted;
};

// Usage
const accountNumber = formatAccountNumber('670 00 00 00');
// Output: "237670000000"

Users Service

Create payout requests after verification

Services Overview

Back to services overview

Build docs developers (and LLMs) love