npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ciwergrp/nestjs-midtrans

v0.1.0

Published

NestJS wrapper for Midtrans configuration and injectable services.

Readme

@ciwergrp/nestjs-midtrans

NestJS module for calling Midtrans APIs from injectable services.

The package currently supports Midtrans Snap transaction creation and payment URL generation. It also supports static configuration, async configuration, per-call runtime configuration, custom fetch wrappers, request/response interceptors, and request timeouts.

Installation

npm install @ciwergrp/nestjs-midtrans

Register the module

Use forRoot() when the Midtrans keys are known when the app starts.

import { Module } from '@nestjs/common';
import { MidtransModule } from '@ciwergrp/nestjs-midtrans';

@Module({
  imports: [
    MidtransModule.forRoot({
      serverKey: process.env.MIDTRANS_SERVER_KEY!,
      clientKey: process.env.MIDTRANS_CLIENT_KEY!,
      environment: 'sandbox',
    }),
  ],
})
export class AppModule {}

Async configuration

Use forRootAsync() when keys come from another Nest provider, such as ConfigService.

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MidtransModule } from '@ciwergrp/nestjs-midtrans';

@Module({
  imports: [
    ConfigModule.forRoot(),
    MidtransModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        serverKey: config.getOrThrow<string>('MIDTRANS_SERVER_KEY'),
        clientKey: config.getOrThrow<string>('MIDTRANS_CLIENT_KEY'),
        environment: config.get<'sandbox' | 'production'>('MIDTRANS_ENVIRONMENT', 'sandbox'),
      }),
    }),
  ],
})
export class AppModule {}

Runtime configuration

Use resolveConfig when the Midtrans keys must be resolved for each API call. This is useful when the keys come from a database or another runtime source and changes should take effect without restarting the app.

import { Module } from '@nestjs/common';
import { MidtransModule } from '@ciwergrp/nestjs-midtrans';
import { PaymentConfigModule } from './payment-config.module';
import { PaymentConfigService } from './payment-config.service';

@Module({
  imports: [
    PaymentConfigModule,
    MidtransModule.forRootAsync({
      imports: [PaymentConfigModule],
      inject: [PaymentConfigService],
      useFactory: (paymentConfig: PaymentConfigService) => ({
        resolveConfig: async (context) => {
          const config = await paymentConfig.getMidtransConfig(context);

          return {
            serverKey: config.serverKey,
            clientKey: config.clientKey,
            environment: config.environment,
          };
        },
      }),
    }),
  ],
})
export class AppModule {}

Pass any project-specific context when calling a Midtrans method:

await this.midtrans.createSnapTransaction(payload, {
  context: {
    configKey: 'store-1',
  },
});

The library does not inspect or require any specific context fields. It only passes the object to resolveConfig.

Per-call configuration

You can also override the Midtrans config for a single call.

await this.midtrans.generateSnapPaymentUrl(payload, {
  config: {
    serverKey: runtimeConfig.serverKey,
    clientKey: runtimeConfig.clientKey,
    environment: runtimeConfig.environment,
  },
});

Per-call config has the highest priority, then resolveConfig, then the static config from forRoot() or forRootAsync().

Default Snap callback URLs

Set snapCallbacks when you want default redirect URLs for Snap transactions.

MidtransModule.forRoot({
  serverKey: process.env.MIDTRANS_SERVER_KEY!,
  clientKey: process.env.MIDTRANS_CLIENT_KEY,
  environment: 'sandbox',
  snapCallbacks: {
    finish: 'https://your-app.com/payment/finish',
    error: 'https://your-app.com/payment/error',
  },
});

These defaults are merged into every Snap transaction payload. Per-transaction callbacks still win, so you can add custom query strings for a specific payment.

await this.midtrans.createSnapTransaction({
  transaction_details: {
    order_id: 'ORDER-101',
    gross_amount: 10000,
  },
  callbacks: {
    finish: `https://your-app.com/payment/finish?order_id=ORDER-101`,
  },
});

Inject in a service

import { Injectable } from '@nestjs/common';
import { MidtransService } from '@ciwergrp/nestjs-midtrans';

@Injectable()
export class PaymentsService {
  constructor(private readonly midtrans: MidtransService) {}

  getMidtransEnvironment() {
    return {
      environment: this.midtrans.environment,
      baseUrl: this.midtrans.baseUrl,
      snapBaseUrl: this.midtrans.snapBaseUrl,
    };
  }
}

Generate a Snap payment URL

import { Injectable } from '@nestjs/common';
import { MidtransService } from '@ciwergrp/nestjs-midtrans';

@Injectable()
export class PaymentsService {
  constructor(private readonly midtrans: MidtransService) {}

  async createPaymentUrl() {
    return this.midtrans.generateSnapPaymentUrl({
      transaction_details: {
        order_id: 'ORDER-101',
        gross_amount: 10000,
      },
      credit_card: {
        secure: true,
      },
    });
  }
}

Use createSnapTransaction() when you need both values returned by Midtrans:

const transaction = await this.midtrans.createSnapTransaction({
  transaction_details: {
    order_id: 'ORDER-101',
    gross_amount: 10000,
  },
});

console.log(transaction.token);
console.log(transaction.redirect_url);

Both Snap methods accept optional request options:

await this.midtrans.createSnapTransaction(payload, {
  context: {
    configKey: 'store-1',
  },
  timeoutMs: 10000,
});

Charge a Core transaction

Core Charge currently supports Bank Transfer and E-Wallet payload types. Core Charge payloads are validated before the request is sent to Midtrans. The package does not rely on Midtrans fallback behavior for payment_type, bank_transfer.bank, QRIS acquirer, or required e-wallet fields. Validation also checks shared fields such as transaction_details, item_details, customer_details, and custom_expiry, and rejects payment-specific objects that do not belong to the selected payment_type.

Bank Transfer examples:

await this.midtrans.chargeCoreTransaction({
  payment_type: 'bank_transfer',
  transaction_details: {
    order_id: 'ORDER-101',
    gross_amount: 10000,
  },
  bank_transfer: {
    bank: 'bca',
  },
});

await this.midtrans.chargeCoreTransaction({
  payment_type: 'permata',
  transaction_details: {
    order_id: 'ORDER-102',
    gross_amount: 10000,
  },
});

await this.midtrans.chargeCoreTransaction({
  payment_type: 'echannel',
  transaction_details: {
    order_id: 'ORDER-103',
    gross_amount: 10000,
  },
  echannel: {
    bill_info1: 'Payment:',
    bill_info2: 'Online purchase',
  },
});

E-Wallet examples:

await this.midtrans.chargeCoreTransaction({
  payment_type: 'gopay',
  transaction_details: {
    order_id: 'ORDER-104',
    gross_amount: 10000,
  },
  gopay: {
    enable_callback: true,
    callback_url: 'https://your-app.com/payment/gopay',
  },
});

await this.midtrans.chargeCoreTransaction({
  payment_type: 'qris',
  transaction_details: {
    order_id: 'ORDER-105',
    gross_amount: 10000,
  },
  qris: {
    acquirer: 'gopay',
  },
});

await this.midtrans.chargeCoreTransaction({
  payment_type: 'shopeepay',
  transaction_details: {
    order_id: 'ORDER-106',
    gross_amount: 10000,
  },
  shopeepay: {
    callback_url: 'https://your-app.com/payment/shopeepay',
  },
});

Core Charge accepts the same optional request options as Snap methods.

Transaction operations

Transaction operations use the Core API base URL and work for both Snap and Core transactions where Midtrans supports the operation.

const status = await this.midtrans.getTransactionStatus('ORDER-101');

console.log(status.transaction_status);

Available methods:

await this.midtrans.getTransactionStatus('ORDER-101');
await this.midtrans.getB2bTransactionStatus('ORDER-101', {
  page: 0,
  perPage: 10,
});
await this.midtrans.approveTransaction('ORDER-101');
await this.midtrans.denyTransaction('ORDER-101');
await this.midtrans.cancelTransaction('ORDER-101');
await this.midtrans.expireTransaction('ORDER-101');
await this.midtrans.refundTransaction('ORDER-101', {
  refund_key: 'ORDER-101-refund-1',
  amount: 5000,
  reason: 'Item out of stock',
});
await this.midtrans.captureTransaction({
  transaction_id: 'transaction-id',
  gross_amount: 10000,
});

These methods accept the same optional request options as Snap methods:

await this.midtrans.getTransactionStatus('ORDER-101', {
  context: {
    configKey: 'store-1',
  },
  timeoutMs: 10000,
});

Custom fetch and interceptors

Use fetch, requestInterceptor, and responseInterceptor to add logging, tracing, retries, custom headers, proxies, or tests around outgoing Midtrans requests.

MidtransModule.forRoot({
  serverKey: process.env.MIDTRANS_SERVER_KEY!,
  clientKey: process.env.MIDTRANS_CLIENT_KEY,
  environment: 'sandbox',
  timeoutMs: 10000,
  fetch: async (url, init) => fetch(url, init),
  requestInterceptor: (request) => {
    console.log('Midtrans request:', request.method, request.url);

    return request;
  },
  responseInterceptor: (response, request) => {
    console.log('Midtrans response:', request.url, response.status);

    return response;
  },
});

The default timeout is 30000 milliseconds. Set timeoutMs: false to disable the package timeout.

Options

| Option | Required | Default | Description | | --- | --- | --- | --- | | serverKey | Yes, unless resolveConfig is used | - | Midtrans server key for backend operations. | | clientKey | No | - | Midtrans client key for frontend/Snap configuration. | | environment | No | sandbox | Either sandbox or production. | | baseUrl | No | Based on environment | Midtrans API base URL override. | | snapBaseUrl | No | Based on environment | Midtrans Snap base URL override. | | snapCallbacks | No | - | Default Snap redirect callback URLs. Payload callbacks override these values. | | isProduction | No | Derived from environment | Compatibility flag matching Midtrans Node.js client config style. | | isGlobal | No | false | Makes the Nest module global when set to true. | | fetch | No | globalThis.fetch | Custom fetch implementation or wrapper. | | requestInterceptor | No | - | Hook called before the request is sent. | | responseInterceptor | No | - | Hook called after a response is received. | | resolveConfig | No | - | Function used to resolve Midtrans config for every API call. | | timeoutMs | No | 30000 | Request timeout in milliseconds. Use false to disable. |

Default URLs:

| Environment | baseUrl | snapBaseUrl | | --- | --- | --- | | sandbox | https://api.sandbox.midtrans.com | https://app.sandbox.midtrans.com/snap | | production | https://api.midtrans.com | https://app.midtrans.com/snap |