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

@sikka/aps

v0.0.24

Published

A Stripe-like developer-friendly SDK for Amazon Payment Services integration. Supports payment links, hosted checkout, tokenization, webhooks, and payment management.

Readme

Amazon Payment Services SDK

npm version License: MIT

A Stripe-like developer-friendly SDK for Amazon Payment Services integration


Features

  • 🚀 Stripe-like DX - Intuitive API design inspired by Stripe
  • ⚛️ React Hooks - useAPS, useCheckout, usePayment hooks for seamless React integration
  • 🧩 React Components - Pre-built components: HostedCheckoutButton, ErrorDisplay, PaymentStatus, TokenizationForm
  • 🔗 Payment Links - Generate shareable payment URLs via official APS API with status tracking
  • 🛒 Hosted Checkout - Full-featured payment pages with 3DS support and recurring payments
  • 💳 Tokenization - Secure card storage for recurring payments with token management
  • 🔄 Recurring Payments - Complete subscription support (UNSCHEDULED, VARIABLE, FIXED modes)
  • 🔔 Webhooks - Real-time payment event notifications with signature verification
  • 💰 Payment Management - Capture, refund, void, and query transactions
  • 🔐 3D Secure - Standard, Standalone, and External 3DS authentication
  • 💱 Multi-Currency - Full support for Middle East currencies + currency conversion
  • 📊 Installments - Buy Now Pay Later with installment payment plans
  • 📦 Batch Processing - Process multiple payments/refunds in batches
  • 🔒 Secure - Proper SHA-256 signature calculation per APS documentation
  • 📦 TypeScript - Full TypeScript support with comprehensive types
  • 🧪 Testing Utilities - Mock client, test cards, and webhook helpers
  • 🛡️ Error Handling - Detailed error messages with suggested actions
  • 🌐 Network Tokenization - Support for card scheme network tokens

Installation

npm install @sikka/aps

Quick Start

1. Initialize the Client

import APS from '@sikka/aps';

const aps = new APS({
  merchantId: process.env.APS_MERCHANT_ID,
  accessCode: process.env.APS_ACCESS_CODE,
  requestSecret: process.env.APS_REQUEST_SECRET,
  responseSecret: process.env.APS_RESPONSE_SECRET,
  environment: 'sandbox' // or 'production'
});

TypeScript Types

All types are exported from the package:

import type {
  APSConfig,
  PaymentResponse,
  PaymentLinkResponse,
  TokenizedCard,
  RefundResponse,
  CaptureResponse,
  VoidResponse,
  WebhookEvent,
  Order,
  Customer,
  TransactionStatus,
  PaymentMethod
} from '@sikka/aps';

2. Create a Payment Link

const link = await aps.paymentLinks.create({
  order: {
    id: 'order_123',
    amount: 10000, // 100.00 SAR (in fils/cents)
    currency: 'SAR',
    description: 'Premium Plan Subscription',
    customer: {
      email: '[email protected]',
      name: 'Ahmed Al-Saud',
      phone: '+966501234567'
    }
  },
  tokenValidityHours: 24 // Link expires in 24 hours
});

console.log('Payment URL:', link.url);
// Send this link to your customer via email, SMS, etc.

3. Create Hosted Checkout

const checkout = await aps.hostedCheckout.create({
  order: {
    id: 'order_456',
    amount: 25000, // 250.00 SAR
    currency: 'SAR',
    description: 'E-commerce Purchase',
    customer: {
      email: '[email protected]', // Required for hosted checkout
      name: 'Ahmed Al-Saud'
    }
  },
  returnUrl: 'https://yoursite.com/api/payment/return', // Use API route to handle POST data
  allowedPaymentMethods: ['card', 'apple_pay', 'mada']
});

// Redirect user to the hosted checkout page
if (checkout.redirectForm) {
  // Create a form and submit to redirectForm.url
  // The customer will be redirected back to returnUrl after payment
}

Important: Hosted Checkout uses return_url for all redirects (success, failure, or cancel).

⚠️ POST Data: APS sends the transaction result as a POST request (form data), not GET query parameters. You need an API route to receive the POST data:

// app/api/payment/return/route.ts
export async function POST(request: NextRequest) {
  const formData = await request.formData();
  
  // Convert to query parameters
  const params = new URLSearchParams();
  formData.forEach((value, key) => {
    if (typeof value === 'string') params.append(key, value);
  });
  
  // Redirect to result page
  return NextResponse.redirect(
    new URL(`/payment/result?${params.toString()}`, request.url)
  );
}

Then use the API route as your returnUrl:

returnUrl: 'https://yoursite.com/api/payment/return'

4. Custom Payment Page (Non-PCI)

Create a custom payment form while APS handles PCI compliance through tokenization.

// Step 1: Get tokenization form (backend)
const tokenizationForm = aps.customPaymentPage.getTokenizationForm({
  returnUrl: 'https://yoursite.com/api/token-result'
});

// Step 2: Render form in your frontend
// <form method="POST" action={tokenizationForm.url}>
//   {Object.entries(tokenizationForm.params).map(([key, value]) => (
//     <input type="hidden" name={key} value={value} />
//   ))}
//   <input name="card_number" placeholder="Card Number" required />
//   <input name="expiry_date" placeholder="MM/YY" required />
//   <input name="card_security_code" placeholder="CVV" required />
//   <input name="card_holder_name" placeholder="Card Holder Name" required />
//   <button type="submit">Pay</button>
// </form>

// Step 3: Handle response at returnUrl (backend)
// Response contains: token_name (and sometimes agreement_id)

// Step 4: Charge with token (backend)
// IMPORTANT: If you do NOT have an agreement_id yet, this is treated as a
// customer-present ECOMMERCE transaction. APS may require 3D Secure.
// Provide returnUrl so the SDK can return a redirectForm when 3DS is needed.
const payment = await aps.customPaymentPage.chargeWithToken({
  order: {
    id: 'order_123',
    amount: 10000, // 100.00 SAR
    currency: 'SAR',
    description: 'Product Purchase'
  },
  tokenName: 'token_from_step_3',
  customerEmail: '[email protected]',
  returnUrl: 'https://yoursite.com/api/payment-return'
});

// Step 5: Save the agreement_id from the successful charge response
// agreement_id is required for future unattended server-to-server charges.

How it works:

  1. Get tokenization form from APS
  2. Render custom form with your branding
  3. Customer enters card details
  4. Form submits to APS (Non-PCI compliant)
  5. APS returns token to your returnUrl
  6. Use token to charge payments server-to-server

Important Notes:

  • Tokenization form collects card details securely (Non-PCI compliant)
  • Card data submits directly to APS, never touches your server
  • Token received at returnUrl can be used for immediate or future charges
  • Use chargeWithToken() for server-to-server payment processing
  • remember_me is a Hosted Checkout parameter — it must NOT be sent to the Payment API PURCHASE endpoint. Doing so can cause APS error 00044 (Token name does not exist).
  • First charge flow: If you only have a token_name (no agreement_id), chargeWithToken() performs a customer-present ECOMMERCE charge. You MUST provide returnUrl to handle 3D Secure redirects. On success, save the agreement_id returned by APS.
  • Recurring flow: For unattended cron-job billing, use aps.recurring.process() with BOTH tokenName AND agreementId. This sends eci: 'RECURRING' and avoids 3DS.

Payments Module (Management)

Manage existing transactions.

// Capture authorized payment
await aps.payments.capture({
  transactionId: string,
  amount?: number  // Optional, full capture if not specified
});

// Refund payment
await aps.payments.refund({
  transactionId: string,
  amount?: number,  // Optional, full refund if not specified
  reason?: string
});

// Void authorization
await aps.payments.void({
  transactionId: string,
  reason?: string
});

// Query transaction
await aps.payments.query({
  transactionId?: string,
  orderId?: string
});

Webhooks Module

Verify and parse webhook events.

// In your API route handler
const signature = request.headers.get('x-aps-signature') || '';
const payload = request.body;

// Verify signature
const isValid = aps.webhooks.verifySignature(
  JSON.stringify(payload),
  signature
);

if (!isValid) {
  return res.status(401).send('Invalid signature');
}

// Construct event
const event = aps.webhooks.constructEvent(payload);

// Handle by type
switch (event.type) {
  case 'payment.success':
  case 'payment.failed':
  case 'payment.pending':
  case 'refund.success':
  case 'refund.failed':
  case 'chargeback.created':
  case 'subscription.renewed':
  case 'subscription.cancelled':
}

Webhook Event Structure:

{
  id: string;
  type: WebhookEventType;
  timestamp: Date;
  data: {
    transactionId: string;
    orderId: string;
    amount: number;
    currency: string;
    status: TransactionStatus;
    paymentMethod?: string;
    metadata?: Record<string, any>;
  };
  rawPayload: object;
}

Supported Payment Methods

| Method | Regions | Description | |--------|---------|-------------| | card | All | Visa, Mastercard, American Express | | apple_pay | All | Apple Pay | | mada | Saudi Arabia | MADA debit cards | | stc_pay | Saudi Arabia | STC Pay wallet | | knet | Kuwait | KNET payment | | naps | Qatar | NAPS payment | | fawry | Egypt | Fawry cash payment | | meeza | Egypt | Meeza cards | | sadad | Saudi Arabia | Sadad payment | | aman | Egypt | Aman installment |

Environment Variables

Create a .env.local file:

# APS Merchant Credentials (from your APS dashboard)
APS_MERCHANT_ID=your_merchant_id
APS_ACCESS_CODE=your_access_code
APS_REQUEST_SECRET=your_request_secret
APS_RESPONSE_SECRET=your_response_secret

# APS Configuration
APS_ENVIRONMENT=sandbox          # Use 'production' for live
APS_CURRENCY=SAR                 # Default currency
APS_LANGUAGE=en                  # Default language

# Your App URL
NEXT_PUBLIC_APP_URL=http://localhost:3000

Supported Currencies

  • SAR - Saudi Riyal
  • AED - UAE Dirham
  • KWD - Kuwaiti Dinar
  • QAR - Qatari Riyal
  • BHD - Bahraini Dinar
  • OMR - Omani Rial
  • JOD - Jordanian Dinar
  • EGP - Egyptian Pound
  • USD - US Dollar
  • EUR - Euro

Error Handling

import { APSException, APSError } from '@sikka/aps';

try {
  const link = await aps.paymentLinks.create({ ... });
} catch (error) {
  if (error instanceof APSException) {
    console.error('Error Code:', error.code);
    console.error('Message:', error.message);
    console.error('Status:', error.statusCode);
    console.error('Details:', error.rawResponse);
    
    // Handle specific errors
    switch (error.code) {
      case 'PAYMENT_LINK_ERROR':
        // Handle payment link creation failure
        break;
      case 'SIGNATURE_ERROR':
        // Handle signature mismatch
        break;
      case 'INVALID_CREDENTIALS':
        // Handle authentication failure
        break;
    }
  } else {
    console.error('Unexpected error:', error);
  }
}

Common Response Codes

| Code | Message | Description | |------|---------|-------------| | 00000 | Success | Transaction successful | | 48000 | Success | Payment link created successfully | | 10030 | Authentication failed | 3DS authentication failed | | 00008 | Signature mismatch | Invalid signature | | 00002 | Invalid parameter | Parameter format error | | 14000 | Declined | Card declined by issuer |

Security Best Practices

  1. Never expose credentials - Always use environment variables
  2. Server-side only - All APS API calls must be server-side
  3. Verify webhooks - Always verify webhook signatures
  4. Use HTTPS - Required for production
  5. PCI Compliance - Use hosted checkout or payment links to avoid PCI scope
  6. Validate amounts - Always validate amounts server-side before creating payments

Testing

Sandbox Environment

const aps = new APS({
  // ... credentials
  environment: 'sandbox'
});

Test Cards (use in sandbox):

| Card Number | Type | CVV | Expiry | |-------------|------|-----|--------| | 4111 1111 1111 1111 | Visa | 123 | 12/25 | | 5297 4100 0000 0002 | MADA | 123 | 12/25 | | 5100 0000 0000 0008 | Mastercard | 123 | 12/25 |

Production

const aps = new APS({
  // ... production credentials
  environment: 'production'
});

Next.js Integration Example

See the included test app for a complete working example:

# Run the test app
pnpm dev

Visit http://localhost:3000 to test payment creation and http://localhost:3000/docs for documentation.

License

MIT License - see LICENSE for details.

Support

For APS-specific issues, contact Amazon Payment Services merchant support: