feat(stripe): optionally name the chosen price on Checkout line items
shop.stripe.line_item_price_name (env SHOP_STRIPE_LINE_ITEM_PRICE_NAME,
default off) appends the price's name to the line item ('Flat Art – A4'),
so a product sold in several named prices shows the buyer which one they
pay for. Off by default: existing shops see no change.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a85bb176d6
commit
961ed5af4c
|
|
@ -193,6 +193,10 @@ return [
|
||||||
'sync_prices' => true,
|
'sync_prices' => true,
|
||||||
'webhook_secret' => env('STRIPE_WEBHOOK_SECRET'),
|
'webhook_secret' => env('STRIPE_WEBHOOK_SECRET'),
|
||||||
|
|
||||||
|
// Append the price's name to the Checkout line item ("Flat Art – A4") when a
|
||||||
|
// product is sold in several named prices. Off by default.
|
||||||
|
'line_item_price_name' => env('SHOP_STRIPE_LINE_ITEM_PRICE_NAME', false),
|
||||||
|
|
||||||
// Webhook events that the shop package listens for
|
// Webhook events that the shop package listens for
|
||||||
// You can customize this list to add/remove events as needed
|
// You can customize this list to add/remove events as needed
|
||||||
'webhook_events' => [
|
'webhook_events' => [
|
||||||
|
|
|
||||||
|
|
@ -2459,6 +2459,13 @@ class Cart extends Model
|
||||||
|
|
||||||
// Get product name (use short_description if available, otherwise name)
|
// Get product name (use short_description if available, otherwise name)
|
||||||
$productName = $product->name ?? 'Product ['.$product->id.']';
|
$productName = $product->name ?? 'Product ['.$product->id.']';
|
||||||
|
|
||||||
|
// Optionally name the chosen option ("Flat Art – A4"), so a product sold in
|
||||||
|
// several prices shows the buyer which one they pay for (shop.stripe.line_item_price_name).
|
||||||
|
$priceName = trim((string) ($priceModel?->name ?? ''));
|
||||||
|
if ($priceName !== '' && config('shop.stripe.line_item_price_name', false)) {
|
||||||
|
$productName .= ' – '.$priceName;
|
||||||
|
}
|
||||||
$description = $product->short_description ?? null;
|
$description = $product->short_description ?? null;
|
||||||
|
|
||||||
// Build description with booking dates if available
|
// Build description with booking dates if available
|
||||||
|
|
|
||||||
|
|
@ -615,4 +615,37 @@ class Session
|
||||||
{
|
{
|
||||||
self::$createCallback = null;
|
self::$createCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function line_item_names_the_chosen_price_only_when_enabled()
|
||||||
|
{
|
||||||
|
config(['shop.stripe.enabled' => true, 'services.stripe.secret' => 'sk_test_fake']);
|
||||||
|
|
||||||
|
$product = Product::factory()->create(['name' => 'Flat Art', 'manage_stock' => false]);
|
||||||
|
ProductPrice::factory()->create([
|
||||||
|
'purchasable_id' => $product->id, 'purchasable_type' => Product::class,
|
||||||
|
'unit_amount' => 5000, 'currency' => 'EUR', 'is_default' => true, 'name' => 'A5',
|
||||||
|
]);
|
||||||
|
$a4 = ProductPrice::factory()->create([
|
||||||
|
'purchasable_id' => $product->id, 'purchasable_type' => Product::class,
|
||||||
|
'unit_amount' => 7000, 'currency' => 'EUR', 'is_default' => false, 'name' => 'A4',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->cart->addToCart($a4, 1);
|
||||||
|
|
||||||
|
$names = [];
|
||||||
|
\Stripe\Checkout\Session::$createCallback = function ($params) use (&$names) {
|
||||||
|
$names[] = $params['line_items'][0]['price_data']['product_data']['name'];
|
||||||
|
$mock = new \stdClass;
|
||||||
|
$mock->id = 'mock_session_id';
|
||||||
|
|
||||||
|
return $mock;
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->cart->checkoutSession(['success_url' => 'https://example.com/s', 'cancel_url' => 'https://example.com/c']);
|
||||||
|
config(['shop.stripe.line_item_price_name' => true]);
|
||||||
|
$this->cart->checkoutSession(['success_url' => 'https://example.com/s', 'cancel_url' => 'https://example.com/c']);
|
||||||
|
|
||||||
|
$this->assertSame(['Flat Art', 'Flat Art – A4'], $names);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue