Skip to content

Commit

Permalink
[14.x] Improve guest Checkout flow (#1439)
Browse files Browse the repository at this point in the history
* Improve guest Checkout flow

* Apply fixes from StyleCI

* wip

Co-authored-by: StyleCI Bot <bot@styleci.io>
  • Loading branch information
driesvints and StyleCIBot authored Sep 23, 2022
1 parent efda679 commit 5ff74af
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 53 deletions.
20 changes: 16 additions & 4 deletions src/Checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,24 @@ public function __construct($owner, Session $session)
/**
* Begin a new guest checkout session.
*
* @param array $sessionOptions
* @return \Laravel\Cashier\Checkout
* @param object|null $parentInstance
* @return \Laravel\Cashier\CheckoutBuilder
*/
public static function guest($parentInstance = null)
{
return new CheckoutBuilder(null, $parentInstance);
}

/**
* Begin a new customer checkout session.
*
* @param \Illuminate\Database\Eloquent\Model $owner
* @param object|null $parentInstance
* @return \Laravel\Cashier\CheckoutBuilder
*/
public static function guest(array $sessionOptions = [])
public static function customer($owner, $parentInstance = null)
{
return static::create(null, $sessionOptions);
return new CheckoutBuilder($owner, $parentInstance);
}

/**
Expand Down
89 changes: 89 additions & 0 deletions src/CheckoutBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Laravel\Cashier;

use Illuminate\Support\Collection;
use Laravel\Cashier\Concerns\AllowsCoupons;
use Laravel\Cashier\Concerns\HandlesTaxes;

class CheckoutBuilder
{
use AllowsCoupons;
use HandlesTaxes;

/**
* The Stripe model instance.
*
* @var \Illuminate\Database\Eloquent\Model|null
*/
protected $owner;

/**
* Create a new checkout builder instance.
*
* @param \Illuminate\Database\Eloquent\Model|null $owner
* @param object|null $parentInstance
* @return void
*/
public function __construct($owner = null, $parentInstance = null)
{
$this->owner = $owner;

if ($parentInstance && in_array(AllowsCoupons::class, class_uses_recursive($parentInstance))) {
$this->couponId = $parentInstance->couponId;
$this->promotionCodeId = $parentInstance->promotionCodeId;
$this->allowPromotionCodes = $parentInstance->allowPromotionCodes;
}

if ($parentInstance && in_array(HandlesTaxes::class, class_uses_recursive($parentInstance))) {
$this->customerIpAddress = $parentInstance->customerIpAddress;
$this->estimationBillingAddress = $parentInstance->estimationBillingAddress;
$this->collectTaxIds = $parentInstance->collectTaxIds;
}
}

/**
* Create a new checkout builder instance.
*
* @param \Illuminate\Database\Eloquent\Model|null $owner
* @param object|null $instance
* @return \Laravel\Cashier\CheckoutBuilder
*/
public static function make($owner = null, $instance = null)
{
return new static($owner, $instance);
}

/**
* Create a new checkout session.
*
* @param array|string $items
* @param array $sessionOptions
* @param array $customerOptions
* @return \Laravel\Cashier\Checkout
*/
public function create($items, array $sessionOptions = [], array $customerOptions = [])
{
$payload = array_filter([
'allow_promotion_codes' => $this->allowPromotionCodes,
'automatic_tax' => $this->automaticTaxPayload(),
'discounts' => $this->checkoutDiscounts(),
'line_items' => Collection::make((array) $items)->map(function ($item, $key) {
if (is_string($key)) {
return ['price' => $key, 'quantity' => $item];
}

$item = is_string($item) ? ['price' => $item] : $item;

$item['quantity'] = $item['quantity'] ?? 1;

return $item;
})->values()->all(),
'tax_id_collection' => [
'enabled' => Cashier::$calculatesTaxes ?: $this->collectTaxIds,
],
]);

return Checkout::create($this->owner, array_merge($payload, $sessionOptions), $customerOptions);
}
}
6 changes: 3 additions & 3 deletions src/Concerns/AllowsCoupons.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ trait AllowsCoupons
*
* @var string|null
*/
protected $couponId;
public $couponId;

/**
* The promotion code ID being applied.
*
* @var string|null
*/
protected $promotionCodeId;
public $promotionCodeId;

/**
* Determines if user redeemable promotion codes are available in Stripe Checkout.
*
* @var bool
*/
protected $allowPromotionCodes = false;
public $allowPromotionCodes = false;

/**
* The coupon ID to be applied.
Expand Down
6 changes: 3 additions & 3 deletions src/Concerns/HandlesTaxes.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ trait HandlesTaxes
*
* @var string|null
*/
protected $customerIpAddress;
public $customerIpAddress;

/**
* The pre-collected billing address used to estimate tax rates when performing "one-off" charges.
*
* @var array
*/
protected $estimationBillingAddress = [];
public $estimationBillingAddress = [];

/**
* Indicates if Tax IDs should be collected during a Stripe Checkout session.
*
* @var bool
*/
protected $collectTaxIds = false;
public $collectTaxIds = false;

/**
* Set the The IP address of the customer used to determine the tax location.
Expand Down
24 changes: 1 addition & 23 deletions src/Concerns/PerformsCharges.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Laravel\Cashier\Concerns;

use Illuminate\Support\Collection;
use Laravel\Cashier\Cashier;
use Laravel\Cashier\Checkout;
use Laravel\Cashier\Payment;
use LogicException;
Expand Down Expand Up @@ -139,27 +137,7 @@ public function refund($paymentIntent, array $options = [])
*/
public function checkout($items, array $sessionOptions = [], array $customerOptions = [])
{
$payload = array_filter([
'allow_promotion_codes' => $this->allowPromotionCodes,
'automatic_tax' => $this->automaticTaxPayload(),
'discounts' => $this->checkoutDiscounts(),
'line_items' => Collection::make((array) $items)->map(function ($item, $key) {
if (is_string($key)) {
return ['price' => $key, 'quantity' => $item];
}

$item = is_string($item) ? ['price' => $item] : $item;

$item['quantity'] = $item['quantity'] ?? 1;

return $item;
})->values()->all(),
'tax_id_collection' => [
'enabled' => Cashier::$calculatesTaxes ?: $this->collectTaxIds,
],
]);

return Checkout::create($this, array_merge($payload, $sessionOptions), $customerOptions);
return Checkout::customer($this, $this)->create($items, $sessionOptions, $customerOptions);
}

/**
Expand Down
10 changes: 2 additions & 8 deletions src/SubscriptionBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -350,22 +350,16 @@ public function checkout(array $sessionOptions = [], array $customerOptions = []
}

$payload = array_filter([
'automatic_tax' => $this->automaticTaxPayload(),
'mode' => 'subscription',
'line_items' => Collection::make($this->items)->values()->all(),
'allow_promotion_codes' => $this->allowPromotionCodes,
'discounts' => $this->checkoutDiscounts(),
'mode' => 'subscription',
'subscription_data' => array_filter([
'default_tax_rates' => $this->getTaxRatesForPayload(),
'trial_end' => $trialEnd ? $trialEnd->getTimestamp() : null,
'metadata' => array_merge($this->metadata, ['name' => $this->name]),
]),
'tax_id_collection' => [
'enabled' => Cashier::$calculatesTaxes ?: $this->collectTaxIds,
],
]);

return Checkout::create($this->owner, array_merge($payload, $sessionOptions), $customerOptions);
return Checkout::customer($this->owner, $this)->create([], array_merge($payload, $sessionOptions), $customerOptions);
}

/**
Expand Down
20 changes: 8 additions & 12 deletions tests/Feature/CheckoutTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,15 @@ public function test_customers_can_start_a_subscription_checkout_session()

public function test_guest_customers_can_start_a_checkout_session()
{
$checkout = Checkout::guest([
'line_items' => [
[
'price_data' => [
'currency' => 'USD',
'product_data' => [
'name' => 'PHP Elephant',
],
'unit_amount' => 200,
],
'quantity' => 1,
],
$shirtPrice = self::stripe()->prices->create([
'currency' => 'USD',
'product_data' => [
'name' => 'T-shirt',
],
'unit_amount' => 1500,
]);

$checkout = Checkout::guest()->create($shirtPrice->id, [
'success_url' => 'http://example.com',
'cancel_url' => 'http://example.com',
]);
Expand Down

0 comments on commit 5ff74af

Please sign in to comment.