Skip to content

Record Maytes payments in Stripe ​

A Maytes order doesn't appear in your Stripe Dashboard, because Stripe takes no payment for it. After you capture, add the order to Stripe as an invoice paid outside Stripe. It then shows in your Stripe Dashboard, and your customer can download a Stripe receipt.

No money moves through Stripe

You're still paid through Maytes settlements.

What you'll see in Stripe ​

  • Invoices: a Paid invoice for the order.
  • Payments: a payment shown as Paid out of band, plus a canceled Payment for Invoice.
  • Receipt: Paid with: Split with Maytes in its header.

Stripe creates the Payment for Invoice when you finalize the invoice, then cancels it when you mark the invoice paid. It moves no money, and you can't avoid it.

Each customer also gets a Maytes receipt for their own share.

What you need ​

Do this from your server, right after capture returns status: "captured". The examples use these values:

In the examplesWhere it comes from
amountThe capture response's amount, in minor units: 4500 is AUD 45.00
currencyThe capture response's currency, in lowercase: AUD becomes aud
orderIdThe capture response's merchant_order_id, or your own order number if you didn't send one
checkoutUuidThe capture response's checkout_uuid, kept in the invoice's metadata so you can match it to the Maytes order

Python and Ruby use order_id and checkout_uuid. Your Stripe secret key is read from STRIPE_SECRET_KEY.

1. Create the customer ​

Create a Stripe customer, or use one you already have. A receipt needs the customer's email address.

ts
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

const customer = await stripe.customers.create({
  name: 'Customer Name',
  email: 'customer@example.com',
});
python
import os
from stripe import StripeClient

stripe = StripeClient(os.environ["STRIPE_SECRET_KEY"])

customer = stripe.v1.customers.create({
    "name": "Customer Name",
    "email": "customer@example.com",
})
php
$stripe = new \Stripe\StripeClient(getenv('STRIPE_SECRET_KEY'));

$customer = $stripe->customers->create([
    'name'  => 'Customer Name',
    'email' => 'customer@example.com',
]);
go
sc := stripe.NewClient(os.Getenv("STRIPE_SECRET_KEY"))

customer, err := sc.V1Customers.Create(ctx, &stripe.CustomerCreateParams{
	Name:  stripe.String("Customer Name"),
	Email: stripe.String("customer@example.com"),
})
if err != nil { /* handle */ }
java
StripeClient stripe = new StripeClient(System.getenv("STRIPE_SECRET_KEY"));

Customer customer = stripe.v1().customers().create(
    CustomerCreateParams.builder()
        .setName("Customer Name")
        .setEmail("customer@example.com")
        .build());
ruby
stripe = Stripe::StripeClient.new(ENV.fetch('STRIPE_SECRET_KEY'))

customer = stripe.v1.customers.create({
  name: 'Customer Name',
  email: 'customer@example.com',
})
csharp
var stripe = new StripeClient(Environment.GetEnvironmentVariable("STRIPE_SECRET_KEY"));

var customer = await stripe.V1.Customers.CreateAsync(new CustomerCreateOptions
{
    Name = "Customer Name",
    Email = "customer@example.com",
});

2. Create the receipt ​

Stripe makes receipts from paid invoices. Create an invoice for the order, finalize it, then mark it as paid outside Stripe.

ts
const invoice = await stripe.invoices.create({
  customer: customer.id,
  currency,
  collection_method: 'send_invoice',
  days_until_due: 0,
  auto_advance: false,
  description: `Order ${orderId}`,
  custom_fields: [{ name: 'Paid with', value: 'Split with Maytes' }],
  metadata: { maytes_checkout_uuid: checkoutUuid },
});

await stripe.invoiceItems.create({
  customer: customer.id,
  invoice: invoice.id,
  amount,
  currency,
  description: `Order ${orderId}`,
});

await stripe.invoices.finalizeInvoice(invoice.id, { auto_advance: false });

await stripe.invoices.pay(invoice.id, { paid_out_of_band: true });
python
invoice = stripe.v1.invoices.create({
    "customer": customer.id,
    "currency": currency,
    "collection_method": "send_invoice",
    "days_until_due": 0,
    "auto_advance": False,
    "description": f"Order {order_id}",
    "custom_fields": [{"name": "Paid with", "value": "Split with Maytes"}],
    "metadata": {"maytes_checkout_uuid": checkout_uuid},
})

stripe.v1.invoice_items.create({
    "customer": customer.id,
    "invoice": invoice.id,
    "amount": amount,
    "currency": currency,
    "description": f"Order {order_id}",
})

stripe.v1.invoices.finalize_invoice(invoice.id, {"auto_advance": False})

stripe.v1.invoices.pay(invoice.id, {"paid_out_of_band": True})
php
$invoice = $stripe->invoices->create([
    'customer'          => $customer->id,
    'currency'          => $currency,
    'collection_method' => 'send_invoice',
    'days_until_due'    => 0,
    'auto_advance'      => false,
    'description'       => "Order {$orderId}",
    'custom_fields'     => [['name' => 'Paid with', 'value' => 'Split with Maytes']],
    'metadata'          => ['maytes_checkout_uuid' => $checkoutUuid],
]);

$stripe->invoiceItems->create([
    'customer'    => $customer->id,
    'invoice'     => $invoice->id,
    'amount'      => $amount,
    'currency'    => $currency,
    'description' => "Order {$orderId}",
]);

$stripe->invoices->finalizeInvoice($invoice->id, ['auto_advance' => false]);

$stripe->invoices->pay($invoice->id, ['paid_out_of_band' => true]);
go
invoice, err := sc.V1Invoices.Create(ctx, &stripe.InvoiceCreateParams{
	Customer:         stripe.String(customer.ID),
	Currency:         stripe.String(currency),
	CollectionMethod: stripe.String("send_invoice"),
	DaysUntilDue:     stripe.Int64(0),
	AutoAdvance:      stripe.Bool(false),
	Description:      stripe.String("Order " + orderId),
	CustomFields: []*stripe.InvoiceCreateCustomFieldParams{
		{Name: stripe.String("Paid with"), Value: stripe.String("Split with Maytes")},
	},
	Metadata: map[string]string{"maytes_checkout_uuid": checkoutUuid},
})
if err != nil { /* handle */ }

_, err = sc.V1InvoiceItems.Create(ctx, &stripe.InvoiceItemCreateParams{
	Customer:    stripe.String(customer.ID),
	Invoice:     stripe.String(invoice.ID),
	Amount:      stripe.Int64(amount),
	Currency:    stripe.String(currency),
	Description: stripe.String("Order " + orderId),
})
if err != nil { /* handle */ }

_, err = sc.V1Invoices.FinalizeInvoice(ctx, invoice.ID, &stripe.InvoiceFinalizeInvoiceParams{
	AutoAdvance: stripe.Bool(false),
})
if err != nil { /* handle */ }

_, err = sc.V1Invoices.Pay(ctx, invoice.ID, &stripe.InvoicePayParams{
	PaidOutOfBand: stripe.Bool(true),
})
if err != nil { /* handle */ }
java
Invoice invoice = stripe.v1().invoices().create(
    InvoiceCreateParams.builder()
        .setCustomer(customer.getId())
        .setCurrency(currency)
        .setCollectionMethod(InvoiceCreateParams.CollectionMethod.SEND_INVOICE)
        .setDaysUntilDue(0L)
        .setAutoAdvance(false)
        .setDescription("Order " + orderId)
        .addCustomField(InvoiceCreateParams.CustomField.builder()
            .setName("Paid with")
            .setValue("Split with Maytes")
            .build())
        .putMetadata("maytes_checkout_uuid", checkoutUuid)
        .build());

stripe.v1().invoiceItems().create(
    InvoiceItemCreateParams.builder()
        .setCustomer(customer.getId())
        .setInvoice(invoice.getId())
        .setAmount(amount)
        .setCurrency(currency)
        .setDescription("Order " + orderId)
        .build());

stripe.v1().invoices().finalizeInvoice(invoice.getId(),
    InvoiceFinalizeInvoiceParams.builder().setAutoAdvance(false).build());

stripe.v1().invoices().pay(invoice.getId(),
    InvoicePayParams.builder().setPaidOutOfBand(true).build());
ruby
invoice = stripe.v1.invoices.create({
  customer: customer.id,
  currency: currency,
  collection_method: 'send_invoice',
  days_until_due: 0,
  auto_advance: false,
  description: "Order #{order_id}",
  custom_fields: [{ name: 'Paid with', value: 'Split with Maytes' }],
  metadata: { maytes_checkout_uuid: checkout_uuid },
})

stripe.v1.invoice_items.create({
  customer: customer.id,
  invoice: invoice.id,
  amount: amount,
  currency: currency,
  description: "Order #{order_id}",
})

stripe.v1.invoices.finalize_invoice(invoice.id, { auto_advance: false })

stripe.v1.invoices.pay(invoice.id, { paid_out_of_band: true })
csharp
var invoice = await stripe.V1.Invoices.CreateAsync(new InvoiceCreateOptions
{
    Customer = customer.Id,
    Currency = currency,
    CollectionMethod = "send_invoice",
    DaysUntilDue = 0,
    AutoAdvance = false,
    Description = $"Order {orderId}",
    CustomFields = new List<InvoiceCustomFieldOptions>
    {
        new InvoiceCustomFieldOptions { Name = "Paid with", Value = "Split with Maytes" },
    },
    Metadata = new Dictionary<string, string> { ["maytes_checkout_uuid"] = checkoutUuid },
});

await stripe.V1.InvoiceItems.CreateAsync(new InvoiceItemCreateOptions
{
    Customer = customer.Id,
    Invoice = invoice.Id,
    Amount = amount,
    Currency = currency,
    Description = $"Order {orderId}",
});

await stripe.V1.Invoices.FinalizeInvoiceAsync(invoice.Id, new InvoiceFinalizeOptions
{
    AutoAdvance = false,
});

await stripe.V1.Invoices.PayAsync(invoice.Id, new InvoicePayOptions
{
    PaidOutOfBand = true,
});

Save the invoice ID with your order for step 3.

auto_advance: false stops Stripe from sending or collecting the invoice. To list each line of your order on the receipt, add one invoice item per line. The items must add up to the captured amount.

3. Show the receipt ​

When your customer views their order, fetch the invoice and link to its hosted_invoice_url. That Stripe page lets them download the receipt.

ts
const { hosted_invoice_url } = await stripe.invoices.retrieve(invoiceId);
python
hosted_invoice_url = stripe.v1.invoices.retrieve(invoice_id).hosted_invoice_url
php
$hostedInvoiceUrl = $stripe->invoices->retrieve($invoiceId)->hosted_invoice_url;
go
inv, err := sc.V1Invoices.Retrieve(ctx, invoiceId, nil)
if err != nil { /* handle */ }
hostedInvoiceURL := inv.HostedInvoiceURL
java
String hostedInvoiceUrl = stripe.v1().invoices().retrieve(invoiceId).getHostedInvoiceUrl();
ruby
hosted_invoice_url = stripe.v1.invoices.retrieve(invoice_id).hosted_invoice_url
csharp
var hostedInvoiceUrl = (await stripe.V1.Invoices.GetAsync(invoiceId)).HostedInvoiceUrl;

Fetch it each time rather than saving the link: Stripe expires it about 30 days after the invoice is finalized.

Link the hosted page, not the invoice PDF

invoice_pdf still shows the amount as due, with a Pay online link.

Good to know ​

  • Add each order once: capture returns captured again if you call it again. Save the invoice ID with your order, and skip if you already have one.
  • Refunds go through Maytes: Stripe refunds nothing for this invoice. Use Maytes refunds.