<?php
namespace App\Services;
use App\Entity\Command;
use App\Entity\Company;
use App\Entity\Location;
use App\Entity\Reservation;
use MangoPay\Check;
use Stripe\Account;
use Stripe\AccountLink;
use Stripe\Checkout\Session;
use Stripe\Refund;
use Stripe\Stripe;
class StripeConnectService extends StripeClient
{
public function __construct(string $stripe_sk)
{
parent::__construct($stripe_sk);
}
/**
* Create a new Stripe account for a connected user.
*
* @param string $type
* @param string $country
* @param string $email
* @return Account
*/
public function createAccount(string $type, string $country, string $email): Account
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$account = $stripe->accounts->create([
'type' => $type,
'country' => $country,
'email' => $email,
]);
return $account;
}
/**
* Retrieve a Stripe account by its ID.
*
* @param string $accountId
* @return Account
*/
public function getAccount(string $accountId): Account
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$account = $stripe->accounts->retrieve($accountId);
return $account;
}
public function createAccountLink(string $accountId, string $returnUrl, string $refreshUrl): AccountLink
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$accountLink = $stripe->accountLinks->create([
'account' => $accountId,
'refresh_url' => $refreshUrl,
'return_url' => $returnUrl,
'type' => 'account_onboarding',
]);
return $accountLink;
}
public function updateAccount(string $accountId, array $params): Account
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$account = $stripe->accounts->update($accountId, $params);
return $account;
}
public function deleteAccount(string $accountId): Account
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$account = $stripe->accounts->delete($accountId);
return $account;
}
public function getAccountBalance(string $accountId)
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$balance = $stripe->balances->retrieve(['stripe_account' => $accountId]);
return $balance;
}
public function createCheckoutSession(
string $connectedAccountID,
string $price,
string $successUrl,
string $cancelUrl
): Session {
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$session = $stripe->checkout->sessions->create([
'payment_method_types' => ['card'],
'mode' => 'payment',
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => 'Custom Payment',
],
'unit_amount' => $price, // amount in cents
],
'quantity' => 1,
]],
'payment_intent_data' => [
// 'application_fee_amount' => 123,
'transfer_data' => ['destination' => $connectedAccountID],
],
'success_url' => $successUrl . "?session_id={CHECKOUT_SESSION_ID}",
'cancel_url' => $cancelUrl
]);
return $session;
}
/**
* Creates a checkout session for locations associated with connected accounts.
*/
public function createCheckoutSessionForLocations(
Location $location,
string $connectedAccountID,
string $price,
string $successUrl,
string $cancelUrl
): Session {
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$appFeeAmount = 0;
foreach ($location->getAppFees() as $appFee) {
$appFeeAmount += $appFee->getValue();
}
$location_cautions_amount = 0;
foreach ($location->getCautions() as $caution) {
$location_cautions_amount += $caution->getMontant();
}
$session = $stripe->checkout->sessions->create([
'mode' => 'payment',
'payment_method_types' => ['card'],
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => $location->getProduct()->getName(),
],
'unit_amount' => $price, // amount in cents
],
'quantity' => 1,
]],
'metadata' => ['location_id' => $location->getId()],
'payment_intent_data' => [
'transfer_group' => 'location_' . $location->getId(),
// 💰 collect a platform fee (in cents)
'application_fee_amount' => $appFeeAmount*100 + $location_cautions_amount*100,
// 🧾 send the remaining amount to the connected account
'transfer_data' => [
'destination' => $connectedAccountID, // connected account ID
]
],
'success_url' => $successUrl . "?session_id={CHECKOUT_SESSION_ID}&client_id=" . $location->getClient()->getId(),
'cancel_url' => $cancelUrl
]);
return $session;
}
public function createCheckoutSessionForProductCommands(
Command $command,
array $line_items,
string $transfer_group,
string $successUrl,
string $cancelUrl
): Session {
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$session = $stripe->checkout->sessions->create([
'line_items' => $line_items,
'payment_intent_data' => ['transfer_group' => $transfer_group],
'metadata' => [
'command_id' => $command->getId(),
'client_id' => $command->getClient()->getId(),
],
'mode' => 'payment',
'success_url' => $successUrl . "?session_id={CHECKOUT_SESSION_ID}",
'cancel_url' => $cancelUrl
]);
return $session;
}
public function createCheckoutSessionForReservations(
Reservation $reservation,
string $connectedAccountID,
string $price,
string $successUrl,
string $cancelUrl
):Session {
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$appFeeAmount = 0;
foreach ($reservation->getAppFees() as $appFee) {
$appFeeAmount += $appFee->getValue();
}
$session = $stripe->checkout->sessions->create([
'line_items' => [[
'price_data' => [
'currency' => 'eur',
'product_data' => [
'name' => $reservation->getProduct()->getName(),
],
'unit_amount' => $price, // amount in cents
],
'quantity' => 1,
]],
'payment_intent_data' => [
'on_behalf_of' => $connectedAccountID,
'transfer_group' => 'RESERVATION' . $reservation->getId(),
// 💰 collect a platform fee (in cents)
'application_fee_amount' => $appFeeAmount*100,
// 🧾 send the remaining amount to the connected account
'transfer_data' => [
'destination' => $connectedAccountID, // connected account ID
]],
'mode' => 'payment',
'success_url' => $successUrl . "?session_id={CHECKOUT_SESSION_ID}",
'cancel_url' => $cancelUrl
]);
return $session;
}
public function retrieveCheckoutSession(string $sessionId): Session
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$session = $stripe->checkout->sessions->retrieve($sessionId);
return $session;
}
public function retrieveInvoice(string $invoiceId)
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$invoice = $stripe->invoices->retrieve($invoiceId);
return $invoice;
}
public function createTransfer(string $amount, string $destinationAccountId, string $chargeId, ?string $currency = 'eur', ?string $description = null)
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$transfer = $stripe->transfers->create([
'amount' => $amount,
'currency' => $currency,
'source_transaction' => $chargeId,
'destination' => $destinationAccountId,
'description' => $description,
]);
return $transfer;
}
public function createTransferReversal(string $transferId, int $amount): \Stripe\TransferReversal
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$reversal = $stripe->transfers->createReversal($transferId, [
'amount' => $amount,
]);
return $reversal;
}
public function retrieveTransfer(string $transferId)
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$transfer = $stripe->transfers->retrieve($transferId);
return $transfer;
}
public function retrieveLatestCharge(string $latestChargeId)
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$charge = $stripe->charges->retrieve($latestChargeId);
return $charge;
}
public function createChargeReversal(string $chargeId, int $amount): Refund
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$charge = $stripe->refunds->create(['charge' => $chargeId, 'amount' => $amount]);
return $charge;
}
/**
* Refund part of an application fee.
*
* @param string $applicationFeeId The fee ID (fee_xxx)
* @param int $amount Amount to refund in cents
*/
public function refundApplicationFee(
string $applicationFeeId,
int $amount
) {
$stripe = new \Stripe\StripeClient($this->stripe_sk);
return $stripe->applicationFees->createRefund(
$applicationFeeId,
[
'amount' => $amount,
]
);
}
public function createStripeLoginLink(string $accountId): \Stripe\LoginLink
{
$stripe = new \Stripe\StripeClient($this->stripe_sk);
$loginLink = $stripe->accounts->createLoginLink($accountId);
return $loginLink;
}
public function getMissingRequirements(Account $account): array
{
return [
'currently_due' => $account->requirements->currently_due,
'past_due' => $account->requirements->past_due,
'eventually_due' => $account->requirements->eventually_due,
'pending_verification' => $account->requirements->pending_verification,
'current_deadline' => $account->requirements->current_deadline ? date('d-m-Y', $account->requirements->current_deadline) : null,
];
}
public function hasMissingRequirements(Account $account): bool
{
return !empty($account->requirements->currently_due)
|| !empty($account->requirements->past_due)
|| !empty($account->requirements->eventually_due);
}
public function formatRequirementsMessages(array $requirements, string $url): array
{
$messages = [];
foreach ($requirements as $category => $fields) {
if ($category == 'currently_due' && !empty($fields)) {
$messages['warning'] = '<p>Votre compte Stripe a des exigences actuellement dues ' . $requirements['current_deadline'] . '.</p> <a href="' . $url . '" class="btn btn-warning">Veuillez les remplir</a></p>';
}
if ($category == 'past_due' && !empty($fields)) {
$messages['danger'] = '<p>Votre compte Stripe a des exigences passées dues.</p> <a href="' . $url . '" class="btn btn-danger">Veuillez les remplir</a>';
}
if ($category == 'eventually_due' && !empty($fields)) {
$messages['info'] = '<p>Votre compte Stripe a des exigences éventuellement dues.</p> <a href="' . $url . '" class="btn btn-info">Veuillez les remplir</a>';
}
if ($category == 'pending_verification' && !empty($fields)) {
$messages['info'] = '<p>Votre compte Stripe a des exigences en attente de vérification.</p> <a href="' . $url . '" class="btn btn-info">Veuillez les vérifier.</a>';
}
}
return $messages;
}
public function isFullyEnabled(Account $account): bool
{
return $account->charges_enabled && $account->payouts_enabled;
}
}