- Inscription sans redirection HelloAsso (acte volontaire séparé) - Génération automatique d'identifiant AlpID (prenom.code mnémotechnique) - Profil en tuiles : identité, compte, mot de passe, OTP, adhésion, adresse, connexions - Double authentification : activation/suppression OTP via Keycloak - Page d'accueil contextuelle (bienvenue si connecté, CTA adhésion si non adhérent) - Historique des connexions avec statistiques et graphiques Chart.js - Géocodage Nominatim + lien OpenStreetMap pour l'adresse - HelloAsso : checkout intent, validation paiement, mise à jour Dolibarr Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
95 lines
3.6 KiB
PHP
95 lines
3.6 KiB
PHP
<?php
|
|
require_once __DIR__ . '/config.php';
|
|
|
|
function _ha_token(): string {
|
|
static $cache = null;
|
|
if ($cache && $cache['expires'] > time()) return $cache['token'];
|
|
|
|
$ch = curl_init('https://api.helloasso.com/oauth2/token');
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => http_build_query([
|
|
'grant_type' => 'client_credentials',
|
|
'client_id' => HA_CLIENT_ID,
|
|
'client_secret' => HA_CLIENT_SECRET,
|
|
]),
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 10,
|
|
]);
|
|
$body = curl_exec($ch);
|
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($status !== 200) {
|
|
throw new RuntimeException("HelloAsso auth échouée ($status): $body");
|
|
}
|
|
$data = json_decode($body, true);
|
|
$cache = ['token' => $data['access_token'], 'expires' => time() + $data['expires_in'] - 30];
|
|
return $cache['token'];
|
|
}
|
|
|
|
// ISO 3166-1 alpha-2 → alpha-3 (HelloAsso exige alpha-3)
|
|
function _ha_country(string $alpha2): string {
|
|
$map = ['FR'=>'FRA','BE'=>'BEL','CH'=>'CHE','LU'=>'LUX','DE'=>'DEU',
|
|
'ES'=>'ESP','IT'=>'ITA','GB'=>'GBR','NL'=>'NLD','PT'=>'PRT'];
|
|
return $map[strtoupper($alpha2)] ?? 'FRA';
|
|
}
|
|
|
|
function ha_create_checkout(string $first_name, string $last_name, string $email, string $kc_uid,
|
|
string $address = '', string $zip = '', string $town = '', string $country = 'FR'): array {
|
|
$token = _ha_token();
|
|
|
|
$return_url = APP_URL . '/helloasso/callback.php?uid=' . urlencode($kc_uid);
|
|
$back_url = APP_URL . '/helloasso/renew.php';
|
|
|
|
$payer = ['firstName' => $first_name, 'lastName' => $last_name, 'email' => $email];
|
|
if ($address) $payer['address'] = $address;
|
|
if ($zip) $payer['zipCode'] = $zip;
|
|
if ($town) $payer['city'] = $town;
|
|
if ($country) $payer['country'] = _ha_country($country);
|
|
|
|
$ch = curl_init('https://api.helloasso.com/v5/organizations/' . HA_ORG_SLUG . '/checkout-intents');
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_POST => true,
|
|
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token", 'Content-Type: application/json'],
|
|
CURLOPT_POSTFIELDS => json_encode([
|
|
'totalAmount' => HA_AMOUNT,
|
|
'initialAmount' => HA_AMOUNT,
|
|
'itemName' => HA_ITEM_NAME,
|
|
'backUrl' => $back_url,
|
|
'errorUrl' => $back_url,
|
|
'returnUrl' => $return_url,
|
|
'containsDonation' => false,
|
|
'payer' => $payer,
|
|
]),
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 15,
|
|
]);
|
|
$body = curl_exec($ch);
|
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($status !== 200 && $status !== 201) {
|
|
throw new RuntimeException("HelloAsso checkout échoué ($status): $body");
|
|
}
|
|
return json_decode($body, true);
|
|
}
|
|
|
|
function ha_get_checkout(string $checkout_intent_id): array {
|
|
$token = _ha_token();
|
|
|
|
$ch = curl_init("https://api.helloasso.com/v5/checkout-intents/$checkout_intent_id");
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 10,
|
|
]);
|
|
$body = curl_exec($ch);
|
|
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($status !== 200) {
|
|
throw new RuntimeException("HelloAsso get checkout échoué ($status): $body");
|
|
}
|
|
return json_decode($body, true);
|
|
}
|