The Simiz NestJS module provides a fully typed, dependency-injection-friendly way to integrate mobile money payments into your NestJS application. It includes a service for creating transactions, a guard for webhook signature verification, and DTOs for request validation.

Prerequisites

RequirementMinimum version
NestJS10.0
Node.js18.0
Simiz accountCreate one free
You need your Simiz API keys before configuring the module. Find them in Dashboard > Settings > API Keys.

Installation

1

Install the packages

npm install @simiz/nestjs @simiz/node-sdk
2

Import the module

Register the Simiz module in your AppModule:
import { SimizModule } from '@simiz/nestjs';

@Module({
  imports: [
    SimizModule.forRoot({
      apiKey: process.env.SIMIZ_API_KEY,
      environment: process.env.SIMIZ_ENVIRONMENT as 'sandbox' | 'production',
      webhookSecret: process.env.SIMIZ_WEBHOOK_SECRET,
    }),
  ],
})
export class AppModule {}
Or use forRootAsync for dynamic configuration:
SimizModule.forRootAsync({
  imports: [ConfigModule],
  inject: [ConfigService],
  useFactory: (config: ConfigService) => ({
    apiKey: config.getOrThrow('SIMIZ_API_KEY'),
    environment: config.getOrThrow('SIMIZ_ENVIRONMENT'),
    webhookSecret: config.getOrThrow('SIMIZ_WEBHOOK_SECRET'),
  }),
}),
3

Set environment variables

SIMIZ_API_KEY=smz_test_xxxxxxxxxxxx
SIMIZ_ENVIRONMENT=sandbox
SIMIZ_WEBHOOK_SECRET=whsec_xxxxxxxxxxxx

Usage

Inject the service

import { SimizService } from '@simiz/nestjs';

@Injectable()
export class PaymentService {
  constructor(private readonly simiz: SimizService) {}

  async createPayment(dto: CreatePaymentDto) {
    const transaction = await this.simiz.createTransaction({
      amount: dto.amount,
      currency: 'XAF',
      phone_number: dto.phoneNumber,
      provider: dto.provider,
      description: dto.description,
      metadata: { orderId: dto.orderId },
    });

    return { checkoutUrl: transaction.checkout_url };
  }

  async getPayment(transactionId: string) {
    return this.simiz.getTransaction(transactionId);
  }
}

Webhook controller

import { SimizWebhookGuard, SimizWebhookPayload } from '@simiz/nestjs';

@Controller('webhooks')
export class WebhookController {
  @Post('simiz')
  @UseGuards(SimizWebhookGuard)
  async handleWebhook(@Body() payload: SimizWebhookPayload) {
    switch (payload.event) {
      case 'transaction.completed':
        // Handle successful payment
        break;
      case 'transaction.failed':
        // Handle failed payment
        break;
      case 'refund.completed':
        // Handle refund
        break;
    }
  }
}
The SimizWebhookGuard automatically verifies the HMAC-SHA256 signature.

DTOs

The package includes built-in DTOs for request validation:
import { CreateTransactionDto, TransactionResponseDto } from '@simiz/nestjs';

Supported payment methods

MethodTypeStatus
Orange MoneyMobile MoneyAvailable
MTN Mobile MoneyMobile MoneyAvailable
WaveMobile MoneyComing Soon
Moov MoneyMobile MoneyComing Soon
Airtel MoneyMobile MoneyComing Soon
M-PesaMobile MoneyComing Soon

Supported currencies

CurrencyCodeCountries
Central African CFA FrancXAFCameroon, Central African Republic, Chad, Congo, Equatorial Guinea, Gabon
West African CFA FrancXOFBenin, Burkina Faso, Ivory Coast, Guinea-Bissau, Mali, Niger, Senegal, Togo
Ghanaian CediGHSGhana
Nigerian NairaNGNNigeria
Kenyan ShillingKESKenya
Ugandan ShillingUGXUganda
Rwandan FrancRWFRwanda
Tanzanian ShillingTZSTanzania

Webhook events

EventDescription
transaction.createdTransaction initiated
transaction.processingBeing processed by the provider
transaction.completedPayment successful
transaction.failedPayment failed
transaction.cancelledCancelled by customer
transaction.expiredPayment window expired
refund.createdRefund initiated
refund.completedRefund completed
refund.failedRefund failed

Test mode

Set the following environment variables:
SIMIZ_API_KEY=smz_test_xxxxxxxxxxxx
SIMIZ_ENVIRONMENT=sandbox
The module connects to sandbox.api.simiz.io and no real money is charged.

Full sandbox documentation

See all test numbers and scenarios in the Sandbox Testing guide.

Troubleshooting

Solutions:
  • Verify SIMIZ_WEBHOOK_SECRET is set correctly
  • Ensure no middleware is parsing the body before the guard (use raw body)
  • Enable raw body in your NestJS app: app.useBodyParser('raw', { type: 'application/json' })

Next steps

Node.js SDK

Explore the underlying Node.js SDK for advanced usage.

Webhook Verification

Learn about webhook configuration and signature verification.

API Reference

Explore the full Simiz API.

Support

Need help? Contact our support team.

Changelog

Version history

VersionDateChanges
1.0.02026-03-01Initial release — mobile money payments, webhooks, sandbox