paid_ads-8.x-1.x-dev/src/Plugin/PaidGateways/PaypalGateway.php
src/Plugin/PaidGateways/PaypalGateway.php
<?php
namespace Drupal\paid_ads\Plugin\PaidGateways;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\paid_ads\Plugin\PaidGatewayInterface;
use Exception;
use GuzzleHttp\ClientInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* Class PaypalGateway. Implements PayPal REST API.
*
* @PaidGateway(
* id = "paypal_gateway",
* label = @Translation("PayPal")
* )
*/
class PaypalGateway extends PluginBase implements PaidGatewayInterface, ContainerFactoryPluginInterface {
/**
* Drupal logger.
*
* @var \Drupal\Core\Logger\LoggerChannel
*/
protected $logger;
/**
* ConfigFactory injection.
*
* @var \Drupal\Core\Config\Config
*/
protected $configurationStorage;
/**
* Drupal entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* Http client.
*
* @var \GuzzleHttp\ClientInterface
*/
protected $httpClient;
/**
* {@inheritdoc}
*/
public function getForm(array $option) {
$amount = $option['amount'] ?? '0.01';
return [
'#theme' => 'paid_ads_paypal_gateway',
'#API_key' => $this->getClientId(),
'#amount' => $amount . '$',
'#attached' => [
'library' => [
'paid_ads/paid_paypal',
],
],
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$values = $this->getOptions();
$form['mode'] = [
'#title' => $this->t('PayPal app mode'),
'#type' => 'select',
'#options' => [
'https://api.sandbox.paypal.com' => $this->t('Sandbox'),
'https://api.paypal.com' => $this->t('Live'),
],
'#default_value' => $values['mode'],
'#description' => $this->t(
'Use the same mode as it set in the app settings on the PayPal dev dashboard'
),
];
$form['client_id'] = [
'#title' => $this->t('Client ID'),
'#type' => 'textfield',
'#default_value' => $values['client_id'] ?? '',
'#description' => $this->t(
'Client ID from sandbox/live API credentials of your PayPal application'
),
];
$form['secret_id'] = [
'#title' => $this->t('Secret ID'),
'#type' => 'textfield',
'#default_value' => $values['secret_id'] ?? '',
'#description' => $this->t(
'Secret ID from sandbox/live API credentials of your PayPal application'
),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$values = $form_state->getValue('form');
$this->setOptions($values);
}
/**
* {@inheritdoc}
*/
public function getPluginId() {
return $this->pluginId;
}
/**
* {@inheritdoc}
*/
public function getPluginDefinition() {
return [];
}
/**
* Gets selected endpoint.
*
* @return string
* API endpoint.
*/
private function getEndpoint() {
return $this->getOptions()['mode'] ?? 'https://api.sandbox.paypal.com';
}
/**
* Gets client ID.
*
* @return string
* Selected client ID.
*/
private function getClientId() {
return $this->getOptions()['client_id'] ?? '';
}
/**
* Gets secrete ID.
*
* @return string
* Secret ID.
*/
private function getSecretId() {
return $this->getOptions()['secret_id'] ?? '';
}
/**
* {@inheritdoc}
*/
public function onCreatePayment(array $context) {
/* @var \Drupal\paid_ads\Entity\PaidPayment $payment */
$payment = $context['payment'];
$jsonArray = [
'intent' => 'CAPTURE',
'application_context' => [
'locale' => 'en-US',
],
'purchase_units' => [
[
'amount' => [
'currency_code' => $payment->getCurrency(),
'value' => $payment->getAmount(),
],
],
],
];
try {
$postResponse = $this->httpClient
->request(
'post',
$this->getEndpoint() . '/v2/checkout/orders',
[
'auth' => [$this->getClientId(), $this->getSecretId()],
'json' => $jsonArray,
'headers' => [
'Prefer' => 'return=representation',
],
]
);
$response = Json::decode($postResponse->getBody());
$payment->setOrderId($response['id']);
}
catch (Exception $exception) {
$this->logger->error(
$this->t(
'Requesting PayPal API ended with the exception @msg',
['@msg' => $exception->getMessage()]
)
);
return JsonResponse::create([], 500);
}
return JsonResponse::create($response);
}
/**
* {@inheritdoc}
*/
public function onApprovePayment(array $context) {
/** @var \Symfony\Component\HttpFoundation\Request $request */
$request = $context['request'];
$paymentId = $request->get('paymentID');
$this->logger->info(
$this->t(
'Confirming payment @id for payer @payer',
[
'@id' => $paymentId,
'@payer' => $request->get('payerID'),
]
)
);
try {
// Map order id with entities.
$response = $this->httpClient->get(
$this->getEndpoint() . '/v2/checkout/orders/' . $paymentId,
[
'auth' => [$this->getClientId(), $this->getSecretId()],
'headers' => [
'Content-Type' => 'application/json',
],
]
);
$order = Json::decode($response->getBody());
if (strtolower($order['status']) === 'completed') {
$payment = $this->entityTypeManager
->getStorage('paid_payment')
->loadByProperties(['order_id' => $order['id']]);
if (count($payment) > 0) {
$payment = reset($payment);
$payment->execute();
$this->logger->info(
$this->t(
'Payment @id confirmed successfully',
['@id' => $payment->getId()]
)
);
}
else {
$this->logger->warning(
$this->t('No entity found for order @id', ['@id' => $paymentId])
);
}
}
else {
$this->logger->warning(
$this->t(
'Trying to approve incompleted order @id',
['@id' => $paymentId]
)
);
}
}
catch (Exception $e) {
$this->logger->error(
$this->t(
'Exception raise on order approval with message @msg',
['@msg' => $e->getMessage()]
)
);
return JsonResponse::create(['status' => 'failed'], 500);
}
return JsonResponse::create(['status' => 'ok']);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('config.factory'),
$container->get('logger.factory'),
$container->get('entity_type.manager'),
$container->get('http_client')
);
}
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, string $plugin_id, $plugin_definition, ConfigFactoryInterface $config, LoggerChannelFactoryInterface $logger, EntityTypeManagerInterface $manager, ClientInterface $client) {
parent::__construct(
$configuration,
$plugin_id,
$plugin_definition,
$config,
$logger
);
$this->configurationStorage = $config->getEditable('paid_ads.settings');
$this->logger = $logger->get($plugin_id);
$this->httpClient = $client;
$this->entityTypeManager = $manager;
}
/**
* {@inheritdoc}
*/
public function setOptions(array $options = []) {
$this->configurationStorage->set('paypal_gateway', $options)
->save();
}
/**
* {@inheritdoc}
*/
public function getOptions() {
return $this->configurationStorage->get('paypal_gateway') ?? [];
}
/**
* {@inheritdoc}
*
* @todo Why it's needed?
*/
public function getConfigForm(array $form, FormStateInterface $form_state) {
return [
'form' => $this->buildConfigurationForm($form, $form_state),
'#tree' => TRUE,
'submit' => [
'#type' => 'submit',
'#value' => $this->t('Save'),
],
];
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
}
}
