HelloAssoApiController.php 8.26 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
<?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;
    }
}