Skip to content

Creating checkouts

The sails.pay.checkout() method creates a payment checkout URL that you can redirect your users to for completing their payment.

Basic usage

js
const checkoutUrl = await sails.pay.checkout({
  amount: 5000,
  email: '[email protected]'
})

The method returns a URL string that you can redirect users to for payment.

Example in an action

Here's a complete example using Actions2:

js
module.exports = {
  friendlyName: 'Create checkout',

  description: 'Create a payment checkout and redirect the user.',

  inputs: {
    amount: {
      type: 'number',
      required: true,
      description: 'The amount to charge in the smallest currency unit.'
    },
    email: {
      type: 'string',
      required: true,
      isEmail: true,
      description: 'The customer email address.'
    }
  },

  exits: {
    success: {
      responseType: 'redirect'
    }
  },

  fn: async function ({ amount, email }) {
    const checkoutUrl = await sails.pay.checkout({
      amount,
      email
    })

    return checkoutUrl
  }
}

Parameters

Parameters vary slightly between adapters. Below are the common parameters and adapter-specific options.

Common parameters

ParameterTypeRequiredDescription
amountNumberYesAmount to charge
emailStringYesCustomer's email address

Paystack parameters

ParameterTypeRequiredDescription
amountNumberYesAmount in the smallest currency unit (kobo for NGN). E.g., 50000 = ₦500.00
emailStringYesCustomer's email address
currencyStringNoTransaction currency. E.g., "NGN", "USD", "GHS"
referenceStringNoUnique transaction reference
callbackUrlStringNoURL to redirect to after payment
planStringNoPlan code for subscription payments
invoiceLimitNumberNoNumber of times to charge customer during subscription
metadataStringNoStringified JSON object of custom data
channelsArrayNoPayment channels to allow: card, bank, ussd, qr, mobile_money, bank_transfer
splitCodeStringNoSplit code for transaction split
subaccountStringNoSubaccount code that owns the payment
transactionChargeNumberNoAmount to override split configuration
bearerStringNoWho bears transaction charges: account or subaccount

Paystack example

js
module.exports = {
  friendlyName: 'Paystack checkout',

  inputs: {
    amount: {
      type: 'number',
      required: true
    },
    email: {
      type: 'string',
      required: true,
      isEmail: true
    }
  },

  exits: {
    success: {
      responseType: 'redirect'
    }
  },

  fn: async function ({ amount, email }) {
    const checkoutUrl = await sails.pay.checkout({
      amount: amount * 100, // Convert to kobo
      email,
      currency: 'NGN',
      callbackUrl: `${sails.config.custom.baseUrl}/payment/verify`,
      channels: ['card', 'bank', 'ussd']
    })

    return checkoutUrl
  }
}

Lemon Squeezy parameters

ParameterTypeRequiredDescription
variantStringYesThe ID of the variant associated with this checkout
customPriceNumberNoCustom price in cents
productOptionsObjectNoOverride product options (name, description, redirect_url)
checkoutOptionsObjectNoCheckout display options (embed, media, logo, dark mode)
checkoutDataObjectNoPrefill data (email, name, billing_address, discount_code)
previewBooleanNoReturn a preview of the checkout
testModeBooleanNoCreate checkout in test mode
expiresAtStringNoISO 8601 date-time when the checkout expires

Lemon Squeezy example

js
module.exports = {
  friendlyName: 'Lemon Squeezy checkout',

  inputs: {
    variantId: {
      type: 'string',
      required: true,
      description: 'The Lemon Squeezy variant ID'
    },
    email: {
      type: 'string',
      required: true,
      isEmail: true
    }
  },

  exits: {
    success: {
      responseType: 'redirect'
    }
  },

  fn: async function ({ variantId, email }) {
    const checkoutUrl = await sails.pay.checkout({
      variant: variantId,
      checkoutData: {
        email
      },
      checkoutOptions: {
        dark: false,
        logo: true
      }
    })

    return checkoutUrl
  }
}

Flutterwave parameters

ParameterTypeRequiredDescription
amountNumberYesAmount to charge (in major currency units). E.g., 5000 = ₦5,000
emailStringYesCustomer's email address
txRefStringYesUnique transaction reference
currencyStringNoTransaction currency. Defaults to "NGN"
redirectUrlStringNoURL to redirect to after payment
customerNameStringNoCustomer's full name
customerPhoneStringNoCustomer's phone number
paymentOptionsStringNoComma-separated payment methods: "card,banktransfer,ussd"
customizationsObjectNoCustomize checkout: title, description, logo
metaObjectNoCustom metadata object

Flutterwave example

js
module.exports = {
  friendlyName: 'Flutterwave checkout',

  inputs: {
    amount: {
      type: 'number',
      required: true
    },
    email: {
      type: 'string',
      required: true,
      isEmail: true
    },
    customerName: {
      type: 'string',
      required: true
    }
  },

  exits: {
    success: {
      responseType: 'redirect'
    }
  },

  fn: async function ({ amount, email, customerName }) {
    const txRef = `TXN-${Date.now()}`

    const checkoutUrl = await sails.pay.checkout({
      amount,
      email,
      customerName,
      txRef,
      currency: 'NGN',
      redirectUrl: `${sails.config.custom.baseUrl}/payment/verify`,
      paymentOptions: 'card,banktransfer,ussd',
      customizations: {
        title: 'My Store',
        description: 'Payment for your order'
      }
    })

    return checkoutUrl
  }
}

Paga parameters

ParameterTypeRequiredDescription
amountNumberYesAmount to charge in the smallest currency unit (kobo for NGN). E.g., 50000 = ₦500.00
emailStringYesCustomer's email address
currencyStringNoTransaction currency. Defaults to "NGN"
paymentReferenceStringNoUnique payment identifier. If not provided, Paga will generate one
chargeUrlStringNoURL to redirect the customer after payment completion
phoneNumberStringNoCustomer's phone number
displayImageStringNoMerchant logo URL to display on checkout
callbackUrlStringNoWebhook URL to receive payment notifications
fundingSourcesStringNoComma-separated list of allowed payment methods: CARD, PAGA, TRANSFER, AGENT, USSD

Paga example

js
module.exports = {
  friendlyName: 'Paga checkout',

  inputs: {
    amount: {
      type: 'number',
      required: true
    },
    email: {
      type: 'string',
      required: true,
      isEmail: true
    }
  },

  exits: {
    success: {
      responseType: 'redirect'
    }
  },

  fn: async function ({ amount, email }) {
    const paymentReference = `ORD-${Date.now()}`

    const checkoutUrl = await sails.pay.checkout({
      amount: amount * 100, // Convert to kobo
      email,
      paymentReference,
      currency: 'NGN',
      chargeUrl: `${sails.config.custom.baseUrl}/payment/complete`,
      callbackUrl: `${sails.config.custom.baseUrl}/webhooks/paga`,
      fundingSources: 'CARD,TRANSFER,USSD'
    })

    return checkoutUrl
  }
}

Using a specific provider

If you have multiple payment providers configured, you can specify which one to use:

js
// Use the default provider
const checkoutUrl = await sails.pay.checkout({ ... })

// Use a specific provider
const checkoutUrl = await sails.pay.provider('paystack').checkout({ ... })

Error handling

The checkout method may throw an error if the checkout URL cannot be created. Handle errors appropriately:

js
module.exports = {
  friendlyName: 'Create checkout',

  inputs: {
    amount: {
      type: 'number',
      required: true
    },
    email: {
      type: 'string',
      required: true,
      isEmail: true
    }
  },

  exits: {
    success: {
      responseType: 'redirect'
    },
    paymentError: {
      responseType: 'view',
      viewTemplatePath: 'pages/payment-error'
    }
  },

  fn: async function ({ amount, email }) {
    try {
      const checkoutUrl = await sails.pay.checkout({
        amount,
        email
      })

      return checkoutUrl
    } catch (error) {
      sails.log.error('Payment checkout error:', error)
      throw 'paymentError'
    }
  }
}

All open source projects are released under the MIT License.