Appearance
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 examples | Where it comes from |
|---|---|
amount | The capture response's amount, in minor units: 4500 is AUD 45.00 |
currency | The capture response's currency, in lowercase: AUD becomes aud |
orderId | The capture response's merchant_order_id, or your own order number if you didn't send one |
checkoutUuid | The 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_urlphp
$hostedInvoiceUrl = $stripe->invoices->retrieve($invoiceId)->hosted_invoice_url;go
inv, err := sc.V1Invoices.Retrieve(ctx, invoiceId, nil)
if err != nil { /* handle */ }
hostedInvoiceURL := inv.HostedInvoiceURLjava
String hostedInvoiceUrl = stripe.v1().invoices().retrieve(invoiceId).getHostedInvoiceUrl();ruby
hosted_invoice_url = stripe.v1.invoices.retrieve(invoice_id).hosted_invoice_urlcsharp
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
capturedagain 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.
