Generate basic order checkout sessions in Paypal with return urls

This commit is contained in:
2024-09-11 14:37:44 +02:00
parent fc8704a2dc
commit 8156a181ea
+123 -3
View File
@@ -2,27 +2,42 @@
namespace App\Library\Economy\Payment;
use App\Controller\GatewaysController;
use App\Entity\GatewayCharge;
use App\Entity\GatewayCheckout;
use App\Entity\GatewayCheckoutLink;
use App\Entity\GatewayCheckoutLinkType;
use Brick\Money\Money as BrickMoney;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\HttpClient\HttpOptions;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
/**
* @see https://developer.paypal.com/studio/checkout/standard/integrate
*/
class PaypalGateway implements GatewayInterface
{
public const PAYPAL_API_ADDRESS_LIVE = 'https://api-m.paypal.com';
public const PAYPAL_API_ADDRESS_SANDBOX = 'https://api-m.sandbox.paypal.com';
/**
* @see https://developer.paypal.com/docs/api/orders/v2/
*/
private const PAYPAL_ORDER_INTENT = 'CAPTURE';
private CacheInterface $cache;
public function __construct(
private string $appEnv,
private string $paypalClientId,
private string $paypalClientSecret,
private RouterInterface $router,
private HttpClientInterface $httpClient,
) {
$this->cache = new FilesystemAdapter();
@@ -50,21 +65,23 @@ class PaypalGateway implements GatewayInterface
}
/**
* Calls the PayPal API to generate an OAuth2 token
* Calls the PayPal API to generate an OAuth2 token.
*
* @return array The API response body
*/
public function generateAuthToken(): array
{
$response = $this->httpClient->request(Request::METHOD_POST, '/v1/oauth2/token', [
'auth_basic' => [$this->paypalClientId, $this->paypalClientSecret],
'body' => 'grant_type=client_credentials'
'body' => 'grant_type=client_credentials',
]);
return $response->toArray();
}
/**
* Retrieves the PayPal OAuth2 token data from cache (if available) or generates a new one
* Retrieves the PayPal OAuth2 token data from cache (if available) or generates a new one.
*
* @return array The OAuth2 token data
*/
public function getAuthToken(): array
@@ -80,6 +97,37 @@ class PaypalGateway implements GatewayInterface
public function sendData(GatewayCheckout $checkout): GatewayCheckout
{
$response = $this->httpClient->request(Request::METHOD_POST, '/v2/checkout/orders', [
'auth_bearer' => $this->getAuthToken()['access_token'],
'json' => [
'intent' => self::PAYPAL_ORDER_INTENT,
'purchase_units' => $this->getPaypalPurchaseUnits($checkout),
'payment_source' => $this->getPaypalPaymentSource()
],
]);
$content = json_decode($response->getContent(), true);
if (!\in_array($response->getStatusCode(), [Response::HTTP_OK, Response::HTTP_CREATED])) {
throw new \Exception($content['message']);
}
$checkout->setGatewayReference($content['id']);
foreach ($content['links'] as $linkData) {
$linkType = \in_array($linkData['rel'], ['approve', 'payer-action'])
? GatewayCheckoutLinkType::Consumer
: GatewayCheckoutLinkType::Platform;
$link = new GatewayCheckoutLink();
$link->setHref($linkData['href']);
$link->setRel($linkData['rel']);
$link->setMethod($linkData['method']);
$link->setType($linkType);
$checkout->addLink($link);
}
return $checkout;
}
@@ -92,4 +140,76 @@ class PaypalGateway implements GatewayInterface
{
return new Response();
}
private function getPaypalMoney(GatewayCharge $charge): array
{
$brick = BrickMoney::ofMinor(
$charge->getMoney()->amount,
$charge->getMoney()->currency
);
return [
'value' => $brick->getAmount()->__toString(),
'currency_code' => $brick->getCurrency()->getCurrencyCode(),
];
}
private function getPaypalReference(GatewayCheckout $checkout, GatewayCharge $charge): string
{
return sprintf('CO%d-CH%d', $checkout->getId(), $charge->getId());
}
private function getPaypalPurchaseUnits(GatewayCheckout $checkout): array
{
$units = [];
foreach ($checkout->getCharges() as $charge) {
$money = $this->getPaypalMoney($charge);
$reference = $this->getPaypalReference($checkout, $charge);
$units[] = [
'reference_id' => $reference,
'items' => [
[
'name' => $charge::MESSAGE_STATEMENT,
'description' => $charge::MESSAGE_STATEMENT,
'quantity' => '1',
'unit_amount' => [
...$money,
],
],
],
'amount' => [
...$money,
'breakdown' => [
'item_total' => [
...$money,
],
],
],
];
}
return $units;
}
private function getPaypalPaymentSource(): array
{
$successUrl = $this->router->generate(
GatewaysController::REDIRECT,
[
'type' => self::RESPONSE_TYPE_SUCCESS,
'gateway' => $this->getName(),
],
RouterInterface::ABSOLUTE_URL
);
return [
'paypal' => [
'experience_context' => [
'return_url' => $successUrl,
],
],
];
}
}