<?php namespace App\Controller; use App\Entity\GlobalParameter; use App\Utils\OperationUtils; use Doctrine\ORM\EntityManagerInterface; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; use League\OAuth2\Client\Provider\GenericProvider; use Psr\Log\LoggerInterface; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security as SecurityS; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Contracts\Cache\ItemInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; class HelloAssoApiController extends AbstractController { protected $client; protected $em; protected $security; protected $translator; protected $eventDispatcher; protected $operationUtils; const CASH_OUT_STATE_MONEY_IN = 'MoneyIn'; const CASH_OUT_STATE_CANT_TRANSFER_RECEIVER_FULL = 'CantTransferReceiverFull'; const CASH_OUT_STATE_TRANSFERED = 'Transfered'; const CASH_OUT_STATE_REFUNDED = 'Refunded'; const CASH_OUT_STATE_REFUNDING = 'Refunding'; const CASH_OUT_STATE_WAITING_FOR_CASH_OUT_CONFIRMATION = 'WaitingForCashOutConfirmation'; const CASH_OUT_STATE_CASHED_OUT = 'CashedOut'; const CASH_OUT_STATE_UNKNOWN = 'Unknown'; const CASH_OUT_STATE_CONTESTED = 'Contested'; const PAYMENT_MEANS_NONE = 'None'; const PAYMENT_MEANS_CARD = 'Card'; const PAYMENT_MEANS_SEPA = 'Sepa'; const PAYMENT_MEANS_CHECK = 'Check'; const STATE_PENDING = 'Pending'; const STATE_AUTHORIZED = 'Authorized'; const STATE_REFUSED = 'Refused'; const STATE_UNKNOWN = 'Unknown'; const STATE_REGISTERED = 'Registered'; const STATE_ERROR = 'Error'; const STATE_REFUNDED = 'Refunded'; const STATE_REFUNDING = 'Refunding'; const STATE_WAITING = 'Waiting'; const STATE_CANCELED = 'Canceled'; const STATE_CONTESTED = 'Contested'; const STATE_WAITING_BANK_VALIDATION = 'WaitingBankValidation'; const STATE_WAITING_BANK_WITHDRAW = 'WaitingBankWithdraw'; const TYPE_OFFLINE = 'Offline'; const TYPE_CREDIT = 'Credit'; const TYPE_DEBIT = 'Debit'; public function __construct( HttpClientInterface $client, Security $security, EntityManagerInterface $em, TranslatorInterface $translator, EventDispatcherInterface $eventDispatcher, LoggerInterface $logger, OperationUtils $operationUtils ) { $this->client = $client; $this->security = $security; $this->em = $em; $this->translator = $translator; $this->eventDispatcher = $eventDispatcher; $this->operationUtils = $operationUtils; } /** * Gets allowable values of the enum. * * @return string[] */ public static function getCashOutStateAllowableValues() { return [ self::CASH_OUT_STATE_MONEY_IN, self::CASH_OUT_STATE_CANT_TRANSFER_RECEIVER_FULL, self::CASH_OUT_STATE_TRANSFERED, self::CASH_OUT_STATE_REFUNDED, self::CASH_OUT_STATE_REFUNDING, self::CASH_OUT_STATE_WAITING_FOR_CASH_OUT_CONFIRMATION, self::CASH_OUT_STATE_CASHED_OUT, self::CASH_OUT_STATE_UNKNOWN, self::CASH_OUT_STATE_CONTESTED, ]; } /** * Gets allowable values of the enum. * * @return string[] */ public static function getPaymentMeansAllowableValues() { return [ self::PAYMENT_MEANS_NONE, self::PAYMENT_MEANS_CARD, self::PAYMENT_MEANS_SEPA, self::PAYMENT_MEANS_CHECK, ]; } /** * Gets allowable values of the enum. * * @return string[] */ public static function getStateAllowableValues() { return [ self::STATE_PENDING, self::STATE_AUTHORIZED, self::STATE_REFUSED, self::STATE_UNKNOWN, self::STATE_REGISTERED, self::STATE_ERROR, self::STATE_REFUNDED, self::STATE_REFUNDING, self::STATE_WAITING, self::STATE_CANCELED, self::STATE_CONTESTED, self::STATE_WAITING_BANK_VALIDATION, self::STATE_WAITING_BANK_WITHDRAW, ]; } /** * Gets allowable values of the enum. * * @return string[] */ public static function getTypeAllowableValues() { return [ self::TYPE_OFFLINE, self::TYPE_CREDIT, self::TYPE_DEBIT, ]; } /** * @Route("/helloasso/sync/orders", name="helloasso_api_synchro") * @SecurityS("(is_granted('ROLE_SUPER_ADMIN') or is_granted('ROLE_ADMIN_SIEGE') or is_granted('ROLE_TRESORIER'))") */ public function synchroItems(int $pageIndex = 1, int $pageSize = 100, Request $request) { $accessToken = $this->authorize(); $cache = new FilesystemAdapter(); // API url to get all payments (> 0) // https://api.helloasso.com/v5/organizations/federation-kohinos/payments // To get all order (>= 0) with free cotisation or example ! $response = $this->client->request('GET', 'https://api.helloasso.com/v5/organizations/federation-kohinos/items?pageSize=' . $pageSize . '&pageIndex=' . $pageIndex, [ 'auth_bearer' => $accessToken->getToken(), ]); $data = $response->toArray(); return new JsonResponse(['data' => $data]); } public function authorize() { $helloClientId = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::HELLOASSO_CLIENTID); $helloClientSecret = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::HELLOASSO_CLIENTSECRET); if (empty($helloClientId) || empty($helloClientSecret)) { throw new \Exception('NO HELLOASSO ID AND SECRET CONFIGURED ! '); } $cache = new FilesystemAdapter(); $provider = new GenericProvider([ 'clientId' => $helloClientId, // The client ID assigned to you by the provider 'clientSecret' => $helloClientSecret, // The client password assigned to you by the provider // 'redirectUri' => 'https://kohinos.test', // Necessary ?! not sure 'urlAuthorize' => 'https://auth.helloasso.com/authorize', // Url for authorization 'urlAccessToken' => 'https://api.helloasso.com/oauth2/token', // Url to get an access token 'urlResourceOwnerDetails' => 'https://api.helloasso.com', // API base endpoint url of Helloasso ]); $value = $cache->get('helloasso_oauth_token2', function (ItemInterface $item) use ($provider) { try { // Try to get an access token using the client credentials grant. $accessToken = $provider->getAccessToken('client_credentials'); } catch (IdentityProviderException $e) { // Failed to get the access token exit($e->getMessage()); } $item->expiresAfter($accessToken->getExpires() - time()); return $accessToken; }); // Item expiresAfter does'nt work ! (don't know why...) So if access token has been expired, get a new one with refresh_token ! if ($value->hasExpired()) { $cache->delete('helloasso_oauth_token2'); $value = $cache->get('helloasso_oauth_token2', function (ItemInterface $item) use ($provider, $value) { try { $newValue = $provider->getAccessToken('refresh_token', [ 'refresh_token' => $value->getRefreshToken(), ]); } catch (IdentityProviderException $e) { // Failed to get the access token exit($e->getMessage()); } $item->expiresAfter($newValue->getExpires() - time()); return $newValue; }); } return $value; } }