Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.launchmystore.io/llms.txt

Use this file to discover all available pages before exploring further.

Payment Customization Functions

Payment customization functions let your app modify which payment methods appear during checkout and how they’re displayed. Use them to hide payment options based on cart contents, rename methods for clarity, or reorder them by preference.

How It Works

Function Manifest

{
  "handle": "my-payment-app",
  "name": "Payment Customizer",
  "version": "1.0.0",
  "functions": {
    "payment_customization": {
      "handle": "payment-rules",
      "name": "Payment Rules",
      "config": {
        "hideCODAbove": 50000,
        "hidePaypalFor": ["subscription", "preorder"]
      }
    }
  }
}

Input Schema

interface PaymentCustomizationInput {
  cart: {
    items: CartItem[];
    subtotal: number;
    total: number;
    currency: string;
    discountCodes: string[];
  };
  paymentMethods: PaymentMethod[];
  shippingAddress: Address | null;
  billingAddress: Address | null;
  customer: {
    id: string;
    email: string;
    tags: string[];
    ordersCount: number;
  } | null;
  shop: {
    id: string;
    currency: string;
  };
}

interface PaymentMethod {
  id: string;           // "credit_card", "paypal", "cod", etc.
  name: string;         // Display name
  type: string;         // "direct", "offsite", "manual"
}

interface CartItem {
  productId: string;
  variantId: string;
  title: string;
  quantity: number;
  price: number;
  productType: string;
  vendor: string;
  tags: string[];
  properties: Record<string, string>;
}

Output Schema

Return an array of operations to apply:
interface PaymentCustomizationOutput {
  operations: PaymentOperation[];
}

type PaymentOperation = 
  | { hide: { paymentMethodId: string } }
  | { rename: { paymentMethodId: string; name: string } }
  | { reorder: { paymentMethodId: string; position: number } };

Operations

Hide Payment Methods

Remove a payment method from checkout:
{
  operations: [
    { hide: { paymentMethodId: 'cod' } },
    { hide: { paymentMethodId: 'bank_transfer' } }
  ]
}

Rename Payment Methods

Change the display name:
{
  operations: [
    { 
      rename: { 
        paymentMethodId: 'credit_card', 
        name: 'Secure Card Payment (Visa, Mastercard, Amex)' 
      } 
    },
    { 
      rename: { 
        paymentMethodId: 'paypal', 
        name: 'PayPal Express Checkout' 
      } 
    }
  ]
}

Reorder Payment Methods

Change the display order (0 = first):
{
  operations: [
    { reorder: { paymentMethodId: 'apple_pay', position: 0 } },
    { reorder: { paymentMethodId: 'credit_card', position: 1 } },
    { reorder: { paymentMethodId: 'paypal', position: 2 } }
  ]
}

Example Implementations

Hide COD for High-Value Orders

function customizePayments(input, config) {
  const operations = [];
  
  // Hide Cash on Delivery for orders over $500
  if (input.cart.total > config.hideCODAbove) {
    operations.push({
      hide: { paymentMethodId: 'cod' }
    });
  }
  
  return { operations };
}

Hide PayPal for Subscriptions

function customizePayments(input, config) {
  const operations = [];
  
  // Check if cart contains subscription products
  const hasSubscription = input.cart.items.some(
    item => item.properties?.subscription_id || 
            item.tags.includes('subscription')
  );
  
  if (hasSubscription) {
    // PayPal doesn't support our subscription flow
    operations.push({
      hide: { paymentMethodId: 'paypal' }
    });
    
    // Rename credit card to indicate recurring billing
    operations.push({
      rename: {
        paymentMethodId: 'credit_card',
        name: 'Credit Card (for recurring payments)'
      }
    });
  }
  
  return { operations };
}

Region-Based Payment Methods

function customizePayments(input, config) {
  const operations = [];
  const country = input.shippingAddress?.countryCode;
  
  // COD only available in specific countries
  const codCountries = ['IN', 'AE', 'SA'];
  if (!codCountries.includes(country)) {
    operations.push({
      hide: { paymentMethodId: 'cod' }
    });
  }
  
  // iDEAL only for Netherlands
  if (country !== 'NL') {
    operations.push({
      hide: { paymentMethodId: 'ideal' }
    });
  }
  
  // Klarna only for Europe
  const klarnaCountries = ['DE', 'AT', 'NL', 'BE', 'FI', 'SE', 'NO', 'DK'];
  if (!klarnaCountries.includes(country)) {
    operations.push({
      hide: { paymentMethodId: 'klarna' }
    });
  }
  
  return { operations };
}

Customer-Based Rules

function customizePayments(input, config) {
  const operations = [];
  const customer = input.customer;
  
  // New customers can't use COD (fraud prevention)
  if (!customer || customer.ordersCount === 0) {
    operations.push({
      hide: { paymentMethodId: 'cod' }
    });
  }
  
  // VIP customers get special payment label
  if (customer?.tags.includes('vip')) {
    operations.push({
      rename: {
        paymentMethodId: 'credit_card',
        name: 'Credit Card (VIP Priority Processing)'
      }
    });
  }
  
  // Wholesale customers must use wire transfer
  if (customer?.tags.includes('wholesale')) {
    operations.push(
      { hide: { paymentMethodId: 'credit_card' } },
      { hide: { paymentMethodId: 'paypal' } },
      { hide: { paymentMethodId: 'cod' } },
      {
        rename: {
          paymentMethodId: 'bank_transfer',
          name: 'Wire Transfer (Net 30)'
        }
      }
    );
  }
  
  return { operations };
}

Product-Based Rules

function customizePayments(input, config) {
  const operations = [];
  
  // Check for restricted product types
  const hasAlcohol = input.cart.items.some(
    item => item.productType === 'alcohol'
  );
  
  const hasDigitalOnly = input.cart.items.every(
    item => item.properties?.digital === 'true'
  );
  
  const hasPreorder = input.cart.items.some(
    item => item.tags.includes('preorder')
  );
  
  // Alcohol: No COD (age verification needed)
  if (hasAlcohol) {
    operations.push({
      hide: { paymentMethodId: 'cod' }
    });
  }
  
  // Digital products: Prioritize instant payments
  if (hasDigitalOnly) {
    operations.push(
      { reorder: { paymentMethodId: 'credit_card', position: 0 } },
      { reorder: { paymentMethodId: 'paypal', position: 1 } },
      { hide: { paymentMethodId: 'cod' } },
      { hide: { paymentMethodId: 'bank_transfer' } }
    );
  }
  
  // Pre-orders: Add note about delayed charge
  if (hasPreorder) {
    operations.push({
      rename: {
        paymentMethodId: 'credit_card',
        name: 'Credit Card (charged when item ships)'
      }
    });
  }
  
  return { operations };
}

Fraud Prevention Rules

function customizePayments(input, config) {
  const operations = [];
  const { cart, shippingAddress, billingAddress, customer } = input;
  
  // High-risk indicators
  const isHighValue = cart.total > 100000; // $1000+
  const isNewCustomer = !customer || customer.ordersCount === 0;
  const addressMismatch = shippingAddress && billingAddress &&
    shippingAddress.countryCode !== billingAddress.countryCode;
  const isHighRiskCountry = ['NG', 'GH', 'KE'].includes(
    shippingAddress?.countryCode
  );
  
  const riskScore = 
    (isHighValue ? 2 : 0) +
    (isNewCustomer ? 1 : 0) +
    (addressMismatch ? 2 : 0) +
    (isHighRiskCountry ? 2 : 0);
  
  // High risk: Only allow verified payments
  if (riskScore >= 4) {
    operations.push(
      { hide: { paymentMethodId: 'cod' } },
      { hide: { paymentMethodId: 'bank_transfer' } },
      {
        rename: {
          paymentMethodId: 'credit_card',
          name: 'Credit Card (3D Secure verification required)'
        }
      }
    );
  }
  
  return { operations };
}

Available Payment Method IDs

Common payment method identifiers:
IDDescription
credit_cardCredit/debit card payments
paypalPayPal
apple_payApple Pay
google_payGoogle Pay
shop_payShop Pay
codCash on Delivery
bank_transferBank/Wire Transfer
klarnaKlarna
afterpayAfterpay
affirmAffirm
idealiDEAL (Netherlands)
sofortSofort (Germany)
The exact payment method IDs available depend on which payment providers the merchant has configured. Your function should handle cases where expected methods don’t exist.

Checkout Display

After your function runs, payment methods are displayed with your modifications:
Payment Method
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

○ Credit Card (VIP Priority Processing)    ← Renamed
  Visa, Mastercard, American Express
  
○ PayPal Express Checkout                  ← Renamed
  
○ Apple Pay                                ← Reordered to position 2

                                           ← COD hidden

Error Handling

Return an empty operations array if no changes needed:
function customizePayments(input, config) {
  // No customizations needed
  return { operations: [] };
}
Handle errors gracefully:
function customizePayments(input, config) {
  try {
    // Your logic here
  } catch (error) {
    // Log error for debugging
    console.error('Payment customization error:', error);
    
    // Return empty operations (show all methods normally)
    return { operations: [] };
  }
}

Testing

Test with various scenarios:
{
  "cart": {
    "items": [{ "title": "Product", "price": 2999 }],
    "total": 2999
  },
  "customer": null,
  "paymentMethods": [
    { "id": "credit_card", "name": "Credit Card" },
    { "id": "paypal", "name": "PayPal" },
    { "id": "cod", "name": "Cash on Delivery" }
  ]
}

Best Practices

Always ensure at least one payment method remains available. Hiding all methods will break checkout.
When renaming methods, keep labels clear and concise. Include relevant info (fees, processing time).
Prioritize mobile-friendly payment methods (Apple Pay, Google Pay) for mobile traffic.
Test with guest checkout, international addresses, and various cart contents.
Keep your payment rules documented so merchants understand why certain methods appear/disappear.

See Also