Split Stripe webhooks: /stripe/webhook for payouts, /stripe/webhook/connect for v2 Connect

- Separate webhook routes with different secrets
- Add verifyConnectWebhookSignature() to StripeService
- Add STRIPE_WEBHOOK_SECRET_CONNECT env var
- Update vault with prod secrets for both endpoints

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-20 22:31:00 +01:00
parent 3ee1bffc2a
commit 3e8eed4edb
5 changed files with 83 additions and 158 deletions

1
.env
View File

@@ -44,6 +44,7 @@ REAL_MAIL=0
STRIPE_PK=
STRIPE_SK=
STRIPE_WEBHOOK_SECRET=
STRIPE_WEBHOOK_SECRET_CONNECT=
STRIPE_MODE=test
SMIME_PASSPHRASE='KLreLnyR07x5h#3$AC'

View File

@@ -10,6 +10,7 @@ OUTSIDE_URL=https://ticket.e-cosplay.fr
STRIPE_PK={{ stripe_pk }}
STRIPE_SK={{ stripe_sk }}
STRIPE_WEBHOOK_SECRET={{ stripe_webhook_secret }}
STRIPE_WEBHOOK_SECRET_CONNECT={{ stripe_webhook_secret_connect }}
STRIPE_MODE=live
SMIME_PASSPHRASE='{{ smime_passphrase }}'
MEILISEARCH_URL=http://meilisearch:7700

View File

@@ -1,157 +1,49 @@
$ANSIBLE_VAULT;1.1;AES256
33656430623666633035373239353664323962323862623437393431623665383235336539623232
3738313536393032323661353331326262636330386563640a353638353539326534313964303233
30656365613636323963643665373039633930303961393730323236633531313561393866303934
3532363532396331320a653636373662383430326131663634643532366562656236643533323734
62393063633663653461626261373532303233623734623630616362633466303232393564633134
61633934353436663162353532393233653836623630346432643034393239643135646164386437
39653431383536336233326635633136633664643165656561366534386561613237633136666666
62343136633839646233303762646162306562316433626562376233356439666230343332636338
38383461386666333835383662383163386239316662356333613132303938646435643934656631
63643164306531616334333437333937333833636435363032313462623332656336643661376337
63623335396235363332373035393232616339663962623964306565323464666266613839653734
61376263646663353631323731666666616434663238386135646564383865663233303731376463
63356536663131636431666166323739373933346136336238393162316635376434333730336266
39356334363835373062343239316331386564326535303964633130333535353834623762636333
39616537666636303663636133303333633265383865653937376131343437333661636130363030
33373735653638313164343331623332346135303235316439336536613766326366643764653832
34613739646535643236613866363533396236303739626331396538646637623030323864633431
62383065333231353364663863653835643230666334393462383332663835626336363661306563
66663033343065306237323330303137353864666365663761663130333239633562376462616336
30653634363139636131396332303538303338666630343566383734393039353261393931636631
65323930313836643632643433373766663462323137366238646233346365353139316563616533
32303839646562653832323136303363336262393831363831353937316331376437613364656635
31626538383166313634353938663066326263666530393635333662353332333731383064616439
37393435636662343933666131656430333139303337623338396432643135343532383337363237
39653436356666613031343833366464613064646635666161373730303762393362633533663734
64373739303864643962623561333838376437313464643434366539656266356165613134346262
66356266623466623063666533306539376436616264306465353066326531656230383565653961
64626534613538313839623062343439366532313762323830396166373932666235343964653533
61333965643931343637613336356461633565396236313262343831633735306562396434363432
36633530626232383836623836373663373232643566343132386335643433646161303139356435
61396166396139303562386437656665633334623061353337313630613164633365633566303635
61666161353864386461653939383164333464303436666265396531653736653033643037656635
30363332323536343831653338643736303064346631356665353131646339346433656162373565
61656561333165376265393635336532336634346565623231343362313465356462333865336137
64663433393462653335383264326338633938663434393532656633353733356237646131353039
64353962356464326465616532666236336163393061623139663465623335393533376362393435
61616465383133303465653538616532626138613534386338623537383664633339326265643536
30303639376535326636383461376439363566346331343865353263653165333035613633396333
63646438366131343438363337373563326366336633663566306334653832303965616435613266
64336461336365386334626364653566663834393134393635333263396633636462303234633031
61363835343761366437653430313237353732326639383761376561623135393235396432643265
38396335646165643531653137636232366634306235623631666362363361663836656365636262
61326138383133366364303735666638376533363935633730316535333366313333633739653563
63326565303163633935616463306234353738656435326333653736663339313136316631313562
39633561633532666661653431343866653839393262383066616533633064323835633538386365
63656634316364663232306663643735366436656137373865626637353065386662663966303236
62663865386165613137383465353735396166633137336437356164666265353738633636393437
34613937646266343130376365613265376632326430636434316366376636623535663963643939
32333137326539653866633533303962333637313163626436356139636639303732383936616235
62326136393965343937306131363062626331363130316334636237613337623930383032636262
32306136353538353831303632663364656633323135376232303330343837353638303835643264
34333136393363353238363436396630616338303463386634313465646361633963313333643034
34633131303034386534623435353936376238373636646638373761633436316363633034646130
34653839393764313136386135373761613162663662383965353164333962343738313733313362
65353564346637383031616231336330633163363561616636323936363932643639336537613333
61346230366661633064653536666238623763343439393034363838353563636466663937613132
31616539396335643965303263336532366131623462313730363865643336353263336464656463
61623133643339313838616232633534373761343333613630633435393638393631613034373464
65366666613830393332306637393534623834323766633636623639616532643566393836333532
32663034653635633362613039653735343131396637343637346338333538613663626433653335
38663564323338666631656362366337636166383862396432326535613261626335636562353034
61656465616566653633613465636236623935336664316264323861623537346135363637623862
39666432613366633232666263373336363539353435666163373761313731646131343636313133
30613437626634643061646661393930343531396230353263396535643366386466643265346662
39643934656432333864346536636662653261616531653235623330333831356266646561326130
63373065636432626232303933636231303965376365373932643236633765303065313037323264
35613061643033363733613538613963386666653733316437343934303731636236636537316363
62633834333138366233383066316662616233376565326132336338313039346633616132376436
66636432326637633230633536373962326332316132356332333538346331303936666666303962
33336262373065383036633163373135386437336635643738306537333563343830616665363130
36663033363961313965666130663561326232653764656437656662323861623337326565373835
64643338373861383836653362363131366462356532396534353863306134343736366661623665
63333434636132636362366237306364393161383966376630643830323861313966373130373938
61346134383636366436653733356265366135633930313737616164363835363830313431383935
66383738356231396261303637623965663837306237383564333336383931366638373662623730
37346432353639343038393834303736623037643965326135633039323236336436363431366537
39396462653834343935326238313036386230646534646464633334633432343338666462633664
33623062306164326161353239383839346236663363373739626339386665386361623931663638
63626563356431653734333236313061623861643831363233663534346134633234663738326362
38623737366232353231613665333833613737356665306261643939653033353736663166646161
37333661376266363833613933653636373835313532306462386635306332366532643634646561
30396530356466313237373538303766373935303132356236666563366530613230663364386430
61303633316635626332623335373533333033306665663030366138633030653035356333633935
65383364376261643837643933386561313137363130643561396636663131373661633536623664
61383066376165376565653931653834636335393630633263636339323962333037656563646538
63366365353735623633316162393932343664333738623434393631343061353733616531633064
31366364646561383062356434306362646532653330633039376438366239396634343838623733
35313337303038346637633666663637613738323363306263376565333566343931643463303264
32646637326633383733343263653763343437393166336630636566316561616134623635323737
34316665366539623234356537333661343965653166333831326461393833333264386439346631
65313239366430646133373461343534613266323134396564343430643638663236643961656463
63333331623562646335383735333935383038656633313562393632643137636564636361373834
35636130306137326433363830333230636532656430323533313463653662626166396532333764
66356465323061613131643738393332656664366239363264616131666637643266313232393934
33333938376564353032616261303336303634633231393036373330353932363335343566396533
39373232366636633135663763333331373637656531393631353739653033663965633163646237
30376638373838613034346236306130633366653135653465313465383730303736323638373365
66643730646338313234333235613235323839383039653536383164343065373132323533636166
36366234386239343465363762396135363139326133306537333837643761343738363864656339
62303465353832613236383361663661366333396336373261343066343463343530333635333866
65616366626136303231313961323361316564643136353830666261616439343832343032323437
34323362386664346431333338333838303030373434316662386461343530653565393233663162
38313365656365616363346638656232353564653638383963316461366662656662313937633439
61613464616432303261363662633036346431633035366262666562663038326432323635363965
33336535626335396232353230383035333235363237313334653264366233626331306564656438
36646334353235316333373731656138633366663433376266393732656132373263663963376435
36313430386664363333633764383965613465613764643662643034663530383934363561636138
61663666363336363937333231373764333039343866333439623839656330306165643633613433
39646639353439346461623035326633653265366231303430333737383334353063353734653165
34643937633131373938306565316332303664623738396163393739363836333135396266346163
62616133663262386263363061643630633736633861626161323039633063333664306436636537
61306337346538333465623539616566336431663731616438626261366566303438383762393839
31623132643532373935656361333638383366643233306531653431346162346137316634636530
61643561623863303036636431383736666233323862343362653462373864636639633835353235
32303666666438663934363938613731613066306161383466353264613030623662343032623964
36663466343762636338353163616137373161376238663932633731643130653462303434393265
37666230393237356362346233363932663861303662306463613531323865393835303939386165
30633964626366616337346562636339386234363935383336646637643031346439653333353931
61303833646539646338316133653439366666376333376331366236663933356164663662383336
32613430393066383162396237383534646561383261626637313838346437643635613931356464
36343162396461333639653438396264326462353831313531356530336662366165626638613738
30336432623436356436613432313334383161353562333237303539353461626239663738336661
35396165343566333965613935623038363663306437316231373935643462383133326434653330
30303537303232343032646530393630376531373832623066323038323833396236633864316632
38643962636334373264376164336566613561373362393738653933643363663762663766633037
39353563376431636339366664656462303866323137326263346262373563386636623930346165
66323565613230333035303038666133623036303862393531636666656333393665653331623531
33616262323332313332646366646133386136633237386163663766323230656338363231353030
66363239626562373039623736316532336134623533366639656535613164666335616632323937
65666333383138333936373934623631323135393338643336383232303362393039626664643261
64386632326535306635663431373832316430323163336330386231373264633635643261393264
65656361663133343339663730313062646165396530383439376566363664363030376438623031
34633464313565383061666564373734633935646661653737313461326331313561613831323464
65343933656430613537363438646463346263663335626339313734303563383038663638636535
62333862303132653361333134653965306437393131383730346537326634343361663661366232
64616465333133626431353337306663663034353165343533356632646666623066656437333563
39626534366435363835376263336565663361383362623431373835636330653734373737313934
38353030653331643963336237366537643738323233623938303337313930383665356666306164
61393537313630323830306130303336346261396635303062666432356166336132636130323766
61313466376161323238303733666166643662386539373733653931343831313338623938636164
33386665643437393564376539383436326131636633646364376339663634633332613437643832
61383031393533386662376536653365343662626261383238356432343062306663323764613237
31373439616635633438653562653433366563356535613835666164666164303634623138383065
62343237356365333761393864383162653961363535313865343463323632363336653265636332
34373562366365323164313262663738353762363266613134336231646666633364356564663838
62316561323237623835303961346362633932336566633335303061363662306663373361316439
34316364346365653066356264633764346162366636663931666531333964663935653436363439
62646431393964393731303561663535663331613164663132326436363236663733613234643735
33616536636434306532646235623135643438646462313434363730316538313539393439363333
63643561313933363438323762623637376463363364386430393638623635303833383938393961
63663830353734656565363639646164643533616430623863313263613164663335316331316663
30616266353866623237333064356264323830613835656365353230643165343961383630633934
61316565626235396562613464323738363937303439666336623930306633383534336162316130
30346634613066333233383163313738356534653461356430626337333663613830663938633039
33376464653166356362643431323438643937623062386330653264653438656566376230653435
36623163343833333035
cloudflare_api_token: Kq_hpaH_ng-hAeGsJo6KhQb2TxYW1v6lRGE84aOR
cloudflare_zone_id: a26d2ecd33d18c984f348eeb060ed5b3
app_secret: 533326ee6417086112c42b1fc1843ff1db82b881988f87442118178ea4469cc2
mailer_dsn: ses+smtp://AKIAWTT2T22CWBRBBDYN:BBdgb6KxRQ8mNcpWFJsZCJxbSGNdgLhKFiITMErfBlQP@default?region=eu-west-3&timeout=120
s3_access_key: CHANGE_ME
s3_secret_key: CHANGE_ME
stripe_pk: pk_live_51SUA1rP4ub49xK2ThoRH8efqGYNi1hrcWMzrqmDtJpMv12cmTzLa8ncJLUKLbOQNZTkm1jgptLfwt4hxEGqkVsHB00AK3ieZNl
stripe_sk: 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
stripe_webhook_secret: whsec_ivqY8C05aJ9mho2N3opJLriO2AuxIqOi
stripe_webhook_secret_connect: whsec_0sG9BPYDysxQst9W6FTp44GpwtO2F6WQ
smime_passphrase: 'EVz5zNV8h4ndSLOCWO9JeaQnIertQm7k'
meilisearch_api_key: bb5a372141164ad715ccffd3338427125e63a3c8feadbe84
meilisearch_master_key: 9e6a86cb9e9b09cdabf30a81e43bdb18892ee0d0ab478a16c50749b8f2ed83e4
db_password: 46eafec68e1e7bc8015790998a2e8ea8b5e31461479588b7
redis_password: 51f7559d1d14a6cf422628537fa562a94481936228e9291d
sonarqube_badge_token: sqb_630fba527176cec0567f773ca0cf87a3195a0f8f
smime_private_key: |
Bag Attributes
localKeyID: 75 15 E3 C2 1D 7B 61 75 99 B9 22 D8 FD A4 19 AC 6B BE 1F 8F
friendlyName: contact@e-cosplay.fr
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC60+PtobUKQsjH
vrRizgwIfR06OkOqYosn17wurYUCZquhGfaRL5nf+qDcOF2liczRfXOsTxnEK0J0
s38JF9zWXTkIms4yfyL9xKOCBEPkNSe03wIcaKQjNB1iuDqW6npUm/ke6VmIAj4q
ig6wwiViqWxkzcE2824RFBI0H4rtkxDNhEXOk6ccVzxz/MwxAvmKHuJQG7LtbysI
KIZcGbNjlm2YmIebVYU44kpI0ZMzfvKsfy9eWX3VyYubpL4Rwsc9I+Z2jsun+nEc
4heHamNu8NrKHWQP802NZvRkMR7t39APYnGcEOBe6eagDkn9DQpZrkxfXYUcteBA
5y3RVBxJAgMBAAECggEASCuXNlJL0blnv0WLgEmRO2w9cKNWRUkI8Wy0rKFqKrnH
nhWd+orVWcEDB98cSdi4Dsrz9sGdtfpyEwvNzJDzxblAUXMfqUEUnswpz41fPpZM
DuJA+gFwOoskuOBq/aZ5eBrCeu7wn4oiQqOPNjfhYkIJdc1H0Lbrs1w6BfmTXN9S
ilSL4GMv7YpEBPt86wiReIbE0DIqaR9Vm1UupkJe7WMc9LrxW6OM4kD5xQTFdJLC
n6QbbX+TE3q+d6TrckK8PeBm+gIX2+NdEuuz7gpZGSybfqN1wqbkziUsifi+7gQi
pxwxhDmCQ08DHplcBdjg1ZldVhaAdHEqCyWZtIZQGwKBgQD9RNXOskPhGBP28oZz
a7APhROKHcEtb9BRj3mwzwIMr3SzJjoBI4SfRR3QcU8jD2uCLNio/cSqjAJVyk2f
Z9wDONnXy4aNrsze0Fx+0t1VqIOVocFDJJHndHCiq2HHorqArvHtZxkj/0xIUx+K
nVltevm7qLSAtR/vWTM1c9Zp/wKBgQC816PZxNEpyg5mgO+3gn5yONsObh2ZyZ/v
KPEmFBjl69AfAxKeaEZaj35RmzdnAFKlv9QzNdAM67+oOIThcaQ+diyNUQegaJwc
amUZHWjQ7RAJNM7lQz85zn9s/MZVC8iNF7xlPWK8Y/ifMwk5e+pAQ79PVwxKiW8y
doXv1uuptwKBgQCPfVJNGr5OZx/YhysZdWd4Q4MAez8ZCQJTUyA0xfN5UGajoQK3
5nGa8sOjdq7JRFE6nUHa7HthzJT+GfHEYElMIgd5tTt0RhaYHiBpUfpIL4LtYYln
Cu8G3Pd7kfGB83YKthMm14Rs2pVTXJTAKcmit0uJwFkTmoqPRlA29nwB7QKBgQCp
iVtzxcwWnW1iPz13XfNRbpPTl66Bg89PMk2VZxOXT6cQQHz1tB39bbf1YclScqrA
XcEPnK9E+l2dk+hQUesnnIaQ9H9JVsFYjXhoHMweTcZIzZ01nLLlnesumJ0ieyq4
6OddaMf85C+wFWyhrAr5WRknDLpfLJWlE11ZnnUCbwKBgQCXOLstj7bEi8N3H8PV
UQlkFKrAmmEE4i3Y3Qqa1DMbm2XJBzPQQJIrDlCeIWs0jk0upOY34W+deWH5gbvW
a/6bpvSzbWqgFD5DnayVkb7CvgEg+CKdUoUumRSs38pet29c/pdKPUxhMq8voIEg
HpnyJcapAiLw0hv4ql380onf0A==
-----END PRIVATE KEY-----

View File

@@ -27,6 +27,28 @@ class StripeWebhookController extends AbstractController
return new Response('Invalid signature', 400);
}
$type = $event->type ?? null;
match ($type) {
'payout.created', 'payout.updated', 'payout.paid', 'payout.failed', 'payout.canceled' => $this->handlePayout($event, $em, $mailerService, $pdfService),
default => null,
};
return new Response('OK', 200);
}
#[Route('/stripe/webhook/connect', name: 'app_stripe_webhook_connect', methods: ['POST'])]
public function webhookConnect(Request $request, StripeService $stripeService, EntityManagerInterface $em): Response
{
$payload = $request->getContent();
$signature = $request->headers->get('Stripe-Signature', '');
$event = $stripeService->verifyConnectWebhookSignature($payload, $signature);
if (!$event) {
return new Response('Invalid signature', 400);
}
$type = $event->type ?? null;
$data = json_decode($payload, true) ?? [];
@@ -36,7 +58,6 @@ class StripeWebhookController extends AbstractController
'v2.core.account.closed' => $this->handleAccountStatus($data, 'closed', $em),
'v2.core.account[configuration.merchant].capability_status_updated' => $this->handleCapabilityUpdate($data, $em),
'v2.core.account[configuration.recipient].capability_status_updated' => $this->handleCapabilityUpdate($data, $em),
'payout.created', 'payout.updated', 'payout.paid', 'payout.failed', 'payout.canceled' => $this->handlePayout($event, $em, $mailerService, $pdfService),
default => null,
};

View File

@@ -16,6 +16,7 @@ class StripeService
public function __construct(
#[Autowire(env: 'STRIPE_SK')] private string $stripeSecret,
#[Autowire(env: 'STRIPE_WEBHOOK_SECRET')] private string $webhookSecret,
#[Autowire(env: 'STRIPE_WEBHOOK_SECRET_CONNECT')] private string $webhookSecretConnect,
#[Autowire(env: 'OUTSIDE_URL')] private string $outsideUrl,
) {
$this->stripe = new StripeClient($this->stripeSecret);
@@ -30,6 +31,15 @@ class StripeService
}
}
public function verifyConnectWebhookSignature(string $payload, string $signature): ?Event
{
try {
return Webhook::constructEvent($payload, $signature, $this->webhookSecretConnect);
} catch (SignatureVerificationException) {
return null;
}
}
/**
* @codeCoverageIgnore Requires live Stripe API
*/