Single Charges

Single Charges

Simple Charge

If you would like to make a one-time charge against a customer, you may use the charge method on a billable model instance. You will need to provide a payment method identifier as the second argument to the charge method:

router.post('/purchase', async ({ request, auth }) => {
const user = auth.getUserOrFail()
const paymentMethodId = request.get('paymentMethodId')
const stripeCharge = await user.charge(100, paymentMethodId)
// ...
})

The charge method accepts an array as its third argument, allowing you to pass any options you wish to the underlying Stripe charge creation. More information regarding the options available to you when creating charges may be found in the Stripe documentation:

await user.charge(100, paymentMethod, {
custom_option: value
})

You may also use the charge method without an underlying customer or user. To accomplish this, invoke the charge method on a new instance of your application's billable model:

await new User().charge(100, paymentMethod)

The charge method will throw an exception if the charge fails. If the charge is successful, an instance of Shopkeeper's Payment will be returned from the method:

try {
const payment = await user.charge(100, paymentMethod)
} catch (e) {
// ...
}

The charge method accepts the payment amount in the lowest denominator of the currency used by your application. For example, if customers are paying in United States Dollars, amounts should be specified in pennies.

Charge With Invoice

Sometimes you may need to make a one-time charge and offer a PDF invoice to your customer. The invoicePrice method lets you do just that. For example, let's invoice a customer for five new shirts:

await user.invoicePrice('price_tshirt', 5)

The invoice will be immediately charged against the user's default payment method. The invoicePrice method also accepts an array as its third argument. This array contains the billing options for the invoice item. The fourth argument accepted by the method is also an array which should contain the billing options for the invoice itself:

await user.invoicePrice('price_tshirt', 5, {
discounts: [
{ coupon: 'SUMMER21SALE' }
]
}, { default_tax_rates: ['txr_id']})

Similarly to invoicePrice, you may use the tabPrice method to create a one-time charge for multiple items (up to 250 items per invoice) by adding them to the customer's "tab" and then invoicing the customer. For example, we may invoice a customer for five shirts and two mugs:

await user.tabPrice('price_tshirt', 5)
await user.tabPrice('price_mug', 2)
await user.invoice()

Alternatively, you may use the invoiceFor method to make a "one-off" charge against the customer's default payment method:

await user.invoiceFor('One Time Fee', 500)

Although the invoiceFor method is available for you to use, it is recommended that you use the invoicePrice and tabPrice methods with pre-defined prices. By doing so, you will have access to better analytics and data within your Stripe dashboard regarding your sales on a per-product basis.

The invoice, invoicePrice, and invoiceFor methods will create a Stripe invoice which will retry failed billing attempts. If you do not want invoices to retry failed charges, you will need to close them using the Stripe API after the first failed charge.

Creating Payment Intents

You can create a new Stripe payment intent by invoking the pay method on a billable model instance. Calling this method will create a payment intent that is wrapped in a Shopkeeper's Payment instance:

router.post('/pay', async ({ request, auth }) => {
const user = auth.getUserOrFail()
const amount = request.get('amount')
const payment = await user.pay(amount)
return payment.clientSecret()
})

After creating the payment intent, you can return the client secret to your application's frontend so that the user can complete the payment in their browser. To read more about building entire payment flows using Stripe payment intents, please consult the Stripe documentation.

When using the pay method, the default payment methods that are enabled within your Stripe dashboard will be available to the customer. Alternatively, if you only want to allow for some specific payment methods to be used, you may use the payWith method:

router.post('/pay', async ({ request, auth }) => {
const user = auth.getUserOrFail()
const amount = request.get('amount')
const payment = await user.pay(amount, ['card', 'bancontact'])
return payment.clientSecret()
})

The pay and payWith methods accept the payment amount in the lowest denominator of the currency used by your application. For example, if customers are paying in United States Dollars, amounts should be specified in pennies.

Refunding Charges

If you need to refund a Stripe charge, you may use the refund method. This method accepts the Stripe payment intent ID as its first argument:

const payment = await user.charge(100, paymentMethodId)
await user.refund(payment.id)