Skip to content

Instantly share code, notes, and snippets.

@Prometee
Last active February 8, 2022 09:48
Show Gist options
  • Save Prometee/8c53130648c6381e75d27812b751d43c to your computer and use it in GitHub Desktop.
Save Prometee/8c53130648c6381e75d27812b751d43c to your computer and use it in GitHub Desktop.
[Sylius] Payum Stripe Checkout Session with Stripe Connect direct charge
<?php
declare(strict_types=1);
namespace App\PayumStripe\Action\StripeCheckoutSession;
use App\PayumStripe\Provider\OnboardedUserInfoProviderInterface;
use ArrayObject;
use FluxSE\PayumStripe\Action\StripeCheckoutSession\CaptureAction;
use FluxSE\PayumStripe\Request\Api\Resource\CreateSession;
use Payum\Core\Request\Generic;
use Stripe\ApiResource;
use Sylius\Component\Core\Model\PaymentInterface;
final class CaptureThirdPartyAction extends CaptureAction
{
private OnboardedUserInfoProviderInterface $onboardedUserInfoProvider;
public function __construct(OnboardedUserInfoProviderInterface $onboardedUserInfoProvider)
{
$this->onboardedUserInfoProvider = $onboardedUserInfoProvider;
}
protected function createApiResource(ArrayObject $model, Generic $request): ApiResource
{
$token = $this->getRequestToken($request);
$model->offsetSet('success_url', $token->getAfterUrl());
$model->offsetSet('cancel_url', $token->getAfterUrl());
$options = [];
$modeDataKey = $this->detectModeData($model);
/** @var PaymentInterface $payment */
$payment = $request->getFirstModel();
$stripeAccount = $this->onboardedUserInfoProvider->getStripeAccountFromPayment($payment);
if ('payment_intent_data' === $modeDataKey && null !== $stripeAccount) {
$this->embedStripeConnectInfo($model, $payment);
$options['stripe_account'] = $stripeAccount;
}
$createRequest = new CreateSession($model->getArrayCopy(), $options);
$this->gateway->execute($createRequest);
return $createRequest->getApiResource();
}
private function embedStripeConnectInfo(ArrayObject $model, PaymentInterface $payment)
{
$paymentIntentData = $model->offsetGet('payment_intent_data');
if (null === $paymentIntentData) {
$paymentIntentData = [];
}
$metadata = [];
if ($model->offsetExists('metadata')) {
$metadata = $model->offsetGet('metadata');
}
$stripeAccount = $this->onboardedUserInfoProvider->getStripeAccountFromPayment($payment);
$applicationFeeAmount = $this->onboardedUserInfoProvider->getApplicationFeeAmountFromPayment($payment);
$paymentIntentData['metadata']['stripe_account'] = $stripeAccount;
$paymentIntentData['application_fee_amount'] = $applicationFeeAmount;
$model->offsetSet('payment_intent_data', $paymentIntentData);
$metadata['stripe_account'] = $stripeAccount;
$model->offsetSet('metadata', $metadata);
}
}
<?php
declare(strict_types=1);
namespace App\PayumStripe\Provider;
use Sylius\Component\Core\Model\PaymentInterface;
interface OnboardedUserInfoProviderInterface
{
public function getStripeAccountFromPayment(PaymentInterface $payment): ?string;
public function getApplicationFeeAmountFromPayment(PaymentInterface $payment): ?int;
}
services:
App\PayumStripe\Provider\OnboardedUserInfoProvider: ~
App\PayumStripe\Action\StripeCheckoutSession\CaptureThirdPartyAction:
public: true
arguments:
$onboardedUserInfoProvider: '@App\PayumStripe\Provider\OnboardedUserInfoProvider'
tags:
- name: payum.action
factory: stripe_checkout_session
alias: app.sylius_payum_stripe.capture_third_party
prepend: true
App\PayumStripe\Action\StripeCheckoutSession\SyncThirdPartyAction:
public: true
tags:
- name: payum.action
factory: stripe_checkout_session
alias: app.sylius_payum_stripe.sync_third_party
prepend: true
<?php
declare(strict_types=1);
namespace App\PayumStripe\Action\StripeCheckoutSession;
use FluxSE\PayumStripe\Action\SyncAction as BaseSyncAction;
use FluxSE\PayumStripe\Request\Api\Resource\RetrieveInterface;
use FluxSE\PayumStripe\Request\Api\Resource\RetrieveSession;
use Payum\Core\Bridge\Spl\ArrayObject;
use Stripe\Checkout\Session;
use Stripe\PaymentIntent;
final class SyncThirdPartyAction extends BaseSyncAction
{
protected function syncSession(ArrayObject $model): void
{
$objectName = (string) $model->offsetGet('object');
if (Session::OBJECT_NAME !== $objectName) {
return;
}
$options = [];
$sessionModeObjectName = PaymentIntent::OBJECT_NAME;
if ($model->offsetExists($sessionModeObjectName)) {
$options = $this->getPaymentIntentOptions($sessionModeObjectName, $model);
}
$sessionRequest = new RetrieveSession(
(string) $model->offsetGet('id'),
$options
);
$this->gateway->execute($sessionRequest);
$session = $sessionRequest->getApiResource();
$model->exchangeArray($session->toArray());
}
protected function findSessionModeIdInSession(ArrayObject $model): ?RetrieveInterface
{
foreach ($this->sessionModes as $sessionModeObjectName => $retrieveRequest) {
$sessionModeId = $model->offsetGet($sessionModeObjectName);
if (empty($sessionModeId)) {
continue;
}
return new $retrieveRequest(
(string) $sessionModeId,
// Added to allow filling the third party `stripe_account`
$this->getPaymentIntentOptions($sessionModeObjectName, $model)
);
}
return null;
}
protected function findSessionModeIdInModeObject(ArrayObject $model): ?RetrieveInterface
{
$objectName = (string) $model->offsetGet('object');
foreach ($this->sessionModes as $sessionModeObjectName => $retrieveRequest) {
if ($sessionModeObjectName !== $objectName) {
continue;
}
$sessionModeId = $model->offsetGet('id');
return new $retrieveRequest(
(string) $sessionModeId,
// Added to allow filling the third party `stripe_account`
$this->getPaymentIntentOptions($sessionModeObjectName, $model)
);
}
return null;
}
private function getPaymentIntentOptions(string $sessionModeObjectName, ArrayObject $model): array
{
$options = [];
$stripeAccount = $model['metadata']['stripe_account'] ?? null;
if (PaymentIntent::OBJECT_NAME === $sessionModeObjectName && null !== $stripeAccount) {
$options['stripe_account'] = $stripeAccount;
}
return $options;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment