Skip to content

Commit

Permalink
Merge pull request #130 from HiEventsDev/revert-127-develop
Browse files Browse the repository at this point in the history
Send customer data and order metadata to Stripe
  • Loading branch information
daveearley authored Aug 7, 2024
2 parents 5ce79bb + b4ed24c commit d0a8a12
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

namespace HiEvents\DomainObjects\Generated;

/**
* THIS FILE IS AUTOGENERATED - DO NOT EDIT IT DIRECTLY.
* @package HiEvents\DomainObjects\Generated
*/
abstract class StripeCustomerDomainObjectAbstract extends \HiEvents\DomainObjects\AbstractDomainObject
{
final public const SINGULAR_NAME = 'stripe_customer';
final public const PLURAL_NAME = 'stripe_customers';
final public const ID = 'id';
final public const NAME = 'name';
final public const EMAIL = 'email';
final public const STRIPE_CUSTOMER_ID = 'stripe_customer_id';
final public const CREATED_AT = 'created_at';
final public const UPDATED_AT = 'updated_at';
final public const DELETED_AT = 'deleted_at';

protected int $id;
protected string $name;
protected string $email;
protected string $stripe_customer_id;
protected ?string $created_at = null;
protected ?string $updated_at = null;
protected ?string $deleted_at = null;

public function toArray(): array
{
return [
'id' => $this->id ?? null,
'name' => $this->name ?? null,
'email' => $this->email ?? null,
'stripe_customer_id' => $this->stripe_customer_id ?? null,
'created_at' => $this->created_at ?? null,
'updated_at' => $this->updated_at ?? null,
'deleted_at' => $this->deleted_at ?? null,
];
}

public function setId(int $id): self
{
$this->id = $id;
return $this;
}

public function getId(): int
{
return $this->id;
}

public function setName(string $name): self
{
$this->name = $name;
return $this;
}

public function getName(): string
{
return $this->name;
}

public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}

public function getEmail(): string
{
return $this->email;
}

public function setStripeCustomerId(string $stripe_customer_id): self
{
$this->stripe_customer_id = $stripe_customer_id;
return $this;
}

public function getStripeCustomerId(): string
{
return $this->stripe_customer_id;
}

public function setCreatedAt(?string $created_at): self
{
$this->created_at = $created_at;
return $this;
}

public function getCreatedAt(): ?string
{
return $this->created_at;
}

public function setUpdatedAt(?string $updated_at): self
{
$this->updated_at = $updated_at;
return $this;
}

public function getUpdatedAt(): ?string
{
return $this->updated_at;
}

public function setDeletedAt(?string $deleted_at): self
{
$this->deleted_at = $deleted_at;
return $this;
}

public function getDeletedAt(): ?string
{
return $this->deleted_at;
}
}
7 changes: 7 additions & 0 deletions backend/app/DomainObjects/StripeCustomerDomainObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace HiEvents\DomainObjects;

class StripeCustomerDomainObject extends Generated\StripeCustomerDomainObjectAbstract
{
}
16 changes: 16 additions & 0 deletions backend/app/Models/StripeCustomer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace HiEvents\Models;

class StripeCustomer extends BaseModel
{
protected function getCastMap(): array
{
return [];
}

protected function getFillableFields(): array
{
return [];
}
}
6 changes: 3 additions & 3 deletions backend/app/Providers/RepositoryServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use HiEvents\Repository\Eloquent\PromoCodeRepository;
use HiEvents\Repository\Eloquent\QuestionAnswerRepository;
use HiEvents\Repository\Eloquent\QuestionRepository;
use HiEvents\Repository\Eloquent\ReservationRepository;
use HiEvents\Repository\Eloquent\StripeCustomerRepository;
use HiEvents\Repository\Eloquent\StripePaymentsRepository;
use HiEvents\Repository\Eloquent\TaxAndFeeRepository;
use HiEvents\Repository\Eloquent\TicketPriceRepository;
Expand All @@ -46,7 +46,7 @@
use HiEvents\Repository\Interfaces\PromoCodeRepositoryInterface;
use HiEvents\Repository\Interfaces\QuestionAnswerRepositoryInterface;
use HiEvents\Repository\Interfaces\QuestionRepositoryInterface;
use HiEvents\Repository\Interfaces\ReservationRepositoryInterface;
use HiEvents\Repository\Interfaces\StripeCustomerRepositoryInterface;
use HiEvents\Repository\Interfaces\StripePaymentsRepositoryInterface;
use HiEvents\Repository\Interfaces\TaxAndFeeRepositoryInterface;
use HiEvents\Repository\Interfaces\TicketPriceRepositoryInterface;
Expand Down Expand Up @@ -83,7 +83,7 @@ class RepositoryServiceProvider extends ServiceProvider
OrganizerRepositoryInterface::class => OrganizerRepository::class,
AccountUserRepositoryInterface::class => AccountUserRepository::class,
CapacityAssignmentRepositoryInterface::class => CapacityAssignmentRepository::class,
ReservationRepositoryInterface::class => ReservationRepository::class,
StripeCustomerRepositoryInterface::class => StripeCustomerRepository::class,
];

public function register(): void
Expand Down
20 changes: 20 additions & 0 deletions backend/app/Repository/Eloquent/StripeCustomerRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace HiEvents\Repository\Eloquent;

use HiEvents\DomainObjects\StripeCustomerDomainObject;
use HiEvents\Models\StripeCustomer;
use HiEvents\Repository\Interfaces\StripeCustomerRepositoryInterface;

class StripeCustomerRepository extends BaseRepository implements StripeCustomerRepositoryInterface
{
protected function getModel(): string
{
return StripeCustomer::class;
}

public function getDomainObject(): string
{
return StripeCustomerDomainObject::class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace HiEvents\Repository\Interfaces;

use HiEvents\DomainObjects\StripeCustomerDomainObject;
use HiEvents\Repository\Eloquent\BaseRepository;

/**
* @extends BaseRepository<StripeCustomerDomainObject>
*/
interface StripeCustomerRepositoryInterface extends RepositoryInterface
{

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

use HiEvents\DataTransferObjects\BaseDTO;
use HiEvents\DomainObjects\AccountDomainObject;
use HiEvents\DomainObjects\OrderDomainObject;

class CreatePaymentIntentRequestDTO extends BaseDTO
{
public function __construct(
public readonly int $amount,
public readonly string $currencyCode,
public AccountDomainObject $account,
public OrderDomainObject $order,
)
{
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@

namespace HiEvents\Services\Domain\Payment\Stripe;

use HiEvents\DomainObjects\StripeCustomerDomainObject;
use HiEvents\Exceptions\Stripe\CreatePaymentIntentFailedException;
use HiEvents\Repository\Interfaces\StripeCustomerRepositoryInterface;
use HiEvents\Services\Domain\Payment\Stripe\DTOs\CreatePaymentIntentRequestDTO;
use HiEvents\Services\Domain\Payment\Stripe\DTOs\CreatePaymentIntentResponseDTO;
use Illuminate\Config\Repository;
use Illuminate\Database\DatabaseManager;
use Psr\Log\LoggerInterface;
use Stripe\Exception\ApiErrorException;
use Stripe\StripeClient;
use Throwable;

readonly class StripePaymentIntentCreationService
class StripePaymentIntentCreationService
{
public function __construct(
private StripeClient $stripeClient,
private LoggerInterface $logger,
private Repository $config,
readonly private StripeClient $stripeClient,
readonly private LoggerInterface $logger,
readonly private Repository $config,
readonly private StripeCustomerRepositoryInterface $stripeCustomerRepository,
readonly private DatabaseManager $databaseManager,
)
{
}
Expand Down Expand Up @@ -47,16 +53,26 @@ public function retrievePaymentIntentClientSecret(

/**
* @throws CreatePaymentIntentFailedException
* @throws ApiErrorException|Throwable
*/
public function createPaymentIntent(CreatePaymentIntentRequestDTO $paymentIntentDTO): CreatePaymentIntentResponseDTO
{
try {
$this->databaseManager->beginTransaction();

$applicationFee = $this->getApplicationFee($paymentIntentDTO);

$paymentIntent = $this->stripeClient->paymentIntents->create([
'amount' => $paymentIntentDTO->amount,
'currency' => $paymentIntentDTO->currencyCode,
'customer' => $this->upsertStripeCustomer($paymentIntentDTO)->getStripeCustomerId(),
'setup_future_usage' => 'on_session',
'metadata' => [
'order_id' => $paymentIntentDTO->order->getId(),
'event_id' => $paymentIntentDTO->order->getEventId(),
'order_short_id' => $paymentIntentDTO->order->getShortId(),
'account_id' => $paymentIntentDTO->account->getId(),
],
'automatic_payment_methods' => [
'enabled' => true,
],
Expand All @@ -68,6 +84,8 @@ public function createPaymentIntent(CreatePaymentIntentRequestDTO $paymentIntent
'paymentIntentDTO' => $paymentIntentDTO->toArray(['account']),
]);

$this->databaseManager->commit();

return new CreatePaymentIntentResponseDTO(
paymentIntentId: $paymentIntent->id,
clientSecret: $paymentIntent->client_secret,
Expand All @@ -82,6 +100,10 @@ public function createPaymentIntent(CreatePaymentIntentRequestDTO $paymentIntent
throw new CreatePaymentIntentFailedException(
__('There was an error communicating with the payment provider. Please try again later.')
);
} catch (Throwable $exception) {
$this->databaseManager->rollBack();

throw $exception;
}
}

Expand Down Expand Up @@ -119,4 +141,46 @@ private function getStripeAccountData(CreatePaymentIntentRequestDTO $paymentInte
'stripe_account' => $paymentIntentDTO->account->getStripeAccountId()
];
}

/**
* @throws ApiErrorException|CreatePaymentIntentFailedException
*/
private function upsertStripeCustomer(CreatePaymentIntentRequestDTO $paymentIntentDTO): StripeCustomerDomainObject
{
$customer = $this->stripeCustomerRepository->findFirstWhere([
'email' => $paymentIntentDTO->order->getEmail(),
]);

if ($customer === null) {
$stripeCustomer = $this->stripeClient->customers->create(
params: [
'email' => $paymentIntentDTO->order->getEmail(),
'name' => $paymentIntentDTO->order->getFullName(),
],
opts: $this->getStripeAccountData($paymentIntentDTO)
);

return $this->stripeCustomerRepository->create([
'name' => $stripeCustomer->name,
'email' => $stripeCustomer->email,
'stripe_customer_id' => $stripeCustomer->id,
]);
}

if ($customer->getName() === $paymentIntentDTO->order->getFullName()) {
return $customer;
}

$stripeCustomer = $this->stripeClient->customers->update(
id: $customer->getStripeCustomerId(),
params: ['name' => $paymentIntentDTO->order->getFullName()],
opts: $this->getStripeAccountData($paymentIntentDTO),
);

$this->stripeCustomerRepository->updateFromArray($customer->getId(), [
'name' => $stripeCustomer->name,
]);

return $customer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public function handle(string $orderShortId): CreatePaymentIntentResponseDTO
'amount' => Money::of($order->getTotalGross(), $order->getCurrency())->getMinorAmount()->toInt(),
'currencyCode' => $order->getCurrency(),
'account' => $account,
'order' => $order,
]));

$this->stripePaymentsRepository->create([
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
public function up(): void
{
Schema::create('stripe_customers', function (Blueprint $table) {
$table->id();

$table->string('name');
$table->string('email');
$table->string('stripe_customer_id');

$table->timestamps();
$table->softDeletes();
});
}

public function down(): void
{
Schema::dropIfExists('stripe_customers');
}
};

0 comments on commit d0a8a12

Please sign in to comment.