alpinux-portail/web/inc/helloasso.php
Alpinux fcdd094e26 Portail membres complet : profil, adhésion, historique, OTP
- 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>
2026-05-04 00:43:38 +02:00

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);
}