Données sur les demandes litigieuses et frauduleuses
Utilisez Sigma ou Data Pipeline pour récupérer des informations sur les litiges et les fraudes.
Le tableau disputes
contient des données relatives à tous les litiges afférents à votre compte. Chaque ligne représente un objet Dispute créé lorsqu’un paiement est contesté. Chaque litige mentionne également toutes les données disponibles sur les preuves de litige qui ont été soumises.
L’exemple suivant fournit des informations préliminaires sur les cinq derniers litiges perdus. Il joint les tables disputes
et charges
à l’aide des colonnes disputes.
et charges.
. En plus de l’ID du litige, chaque ligne contient l’ID du paiement correspondant, le montant, ainsi que le résultat des vérifications du code postal et du code CVC.
select date_format(date_trunc('day', disputes.created), '%m-%d-%Y') as day, disputes.id, disputes.charge_id, disputes.amount, charges.card_address_zip_check as zip, charges.card_cvc_check as cvc from disputes inner join charges on charges.id=disputes.charge_id where disputes.status = 'lost' and disputes.reason = 'fraudulent' order by day desc limit 5
jour | id | charge_id | montant | code postal | cvc |
---|---|---|---|---|---|
dp_vOMx5YyQvnFAiIq | ch_FW6VhruFhbuooR2 | 1 000 | réussite | ||
dp_VXMfERsDEpFFiNO | ch_Xj1ZQ06IJHG4RsI | 1 000 | réussite | échec | |
dp_XA7SGxyvJdrxIYC | ch_EPHENpxtlIS2MiT | 1 000 | échec | échec | |
dp_yZJ6kyRZ271pJTW | ch_tRH5Fl58K2cSJJG | 1 000 | réussite | ||
dp_sPlRTw7CiHirCy9 | ch_1qwkkE3zTseodSq | 1 000 | réussite |
En utilisant Sigma ou Data Pipeline pour générer des rapports sur vos litiges, vous pourrez ainsi identifier les paiements frauduleux et les prévenir grâce à Radar.
Données Radar for Fraud Teams
Si vous utilisez Radar for Fraud Teams, vous avez accès à un tableau radar_
qui contient toutes les règles Radar personnalisées avec leur action et leur prédicat. Vous pouvez vous en servir pour obtenir le rule_
qui peut ensuite être utilisé dans le tableau rule_
pour trouver tous les paiements affectés par les règles. Cette méthode est plus flexible que l’examen de l’attribut outcome_
dans le tableau charges
, car il affiche également les règles 3DS déclenchées pour les Paiement Intents et Setup Intents. Les règles intégrées de Radar ont des ID de règle fixes.
L’exemple suivant montre les paiements récents autorisés en vertu d’une liste blanche et leur score Radar afin de vérifier si des paiements potentiellement frauduleux ont été autorisés :
select outcome_type, card_cvc_check, count(*) as cnt, avg(outcome_risk_score) as avg_risk_score from charges where outcome_rule_id = 'allow_if_in_allowlist' and created >= current_date - interval '14' day group by 1, 2
Platform data
Les entreprises de paiements à destination de plusieurs bénéficiaires, tels que les plateformes Connect, doivent répondre à des exigences particulières en matière de gestion des risques. Voici un exemple de liste d’entreprises recevant des paiements indirects sur votre plateforme, classées par taux de litige :
select m.value as merchant_external_account_id, c.destination_id, arbitrary(a.business_name) as destination_name, count(*) as cnt_charges, count_if(c.paid) as cnt_success_charges, count_if(c.paid) * 1.0 / count(*) as success_rate, if( count_if(dispute_id is not null) > 0, count_if(c.paid) * 1.0 / count_if(c.paid), 0.0 ) as dispute_rate from charges c left join charges_metadata m on m.charge_id = c.id and m.key = 'merchant_external_account_id' join connected_accounts a on a.id = c.destination_id where c.created >= current_date - interval '120' day group by 1,2 order by dispute_rate desc
3D Secure Data
Sigma et Data Pipelines contiennent des données sur l’authentification 3D Secure (3DS). Cet exemple plus complexe montre, pour chaque règle 3DS, combien de fois l’authentification 3DS a été déclenchée et quels ont été les résultats, sachant qu’il peut y avoir plus d’une tentative :
select rd.rule_id, count(distinct rd.id) as cnt_rule_triggered, count(distinct rd.payment_intent_id) * 1.0 / count(distinct rd.id) * 100.0 as pct_pis, count_if(at.is_final_attempt) * 1.0 / count(distinct rd.id) * 100.0 as pct_final_attempts, count_if( at.is_final_attempt and at.threeds_outcome_result = 'authenticated' ) * 1.0 / count(distinct rd.id) * 100.0 as pct_3ds_final_authenticated, count_if( at.threeds_outcome_result = 'authenticated' and at.charge_outcome = 'authorized' ) * 1.0 / count(distinct rd.id) * 100.0 as pct_3ds_authorized from rule_decisions rd left join authentication_report_attempts at on at.intent_id = rd.payment_intent_id where action = 'request_credentials' and rd.created >= current_date - interval '30' day group by 1
All Radar Rule Attributes and Decisions
Vous avez également accès au tableau radar_
. Chaque ligne contient la plupart des valeurs des attributs de règles Radar pour un seul paiement. Vous pouvez joindre les tableaux radar_
et disputes
à l’aide des colonnes radar_
et disputes.
, ce qui vous permet de rédiger des règles ciblant vos litiges et de comprendre les tendances de vos bons et mauvais clients.
select card_3d_secure_support, is_3d_secure_authenticated, cvc_check, avg(risk_score) as avg_risk_score, avg(total_charges_per_card_number_all_time) as avg_total_charges_per_card_number_all_time, count(*) as cnt_disputes from radar_rule_attributes r join disputes d on r.transaction_id = d.charge_id where d.created >= current_date - interval '60' day group by 1,2,3 order by cnt_disputes desc
Pour en savoir plus sur les colonnes disponibles, consultez notre guide Optimiser votre gestion de la fraude sur la durée avec Radar for Fraud Teams et Stripe Data. Il explique, par exemple, où trouver les scores Radar par paiement, etc.
Suivi de programmes de surveillance
Les indicateurs du programme de surveillance des marques de cartes sont difficiles à suivre car les règles sont très spécifiques. Certaines informations sont essentielles, comme le volume ou le nombre de transactions. Leur suivi est nécessaire pour estimer les niveaux de fraude et de contestation de paiement et prendre des mesures rapidement, car les notifications du programme de surveillance ne sont pas immédiates. Nous vous recommandons un processus continu pour suivre les indicateurs relatifs aux contestations de paiement et à la fraude.
Avec Sigma, vous avez la possibilité de rédiger une requête pour estimer les niveaux de fraude, qui simule la façon dont les programmes de surveillance des cartes peuvent évaluer vos paiements. La requête ci-dessous n’est pas parfaite (par exemple, nous partons du principe qu’il s’agit d’un marchand américain pour lesquels les paiements nationaux et transfrontaliers sont comptabilisés, mais vous pouvez ajuster la requête en fonction de votre cas d’usage). Plus important encore, cette requête prend en compte les taux de change de devise, et applique la même méthode de prise en compte indépendante des périodes de paiement et de fraude que les programmes de surveillance.
with exchange_rates as ( select date, currency, rate from exchange_rates_from_usd cross join unnest ( cast( json_parse(buy_currency_exchange_rates) as map(varchar, double) ) ) as t(currency, rate) where date = ( select max(date) from exchange_rates_from_usd ) -- note the calculation for jpy is decimal and may look off ), payments as ( select -- technically these values are calculated per statement descriptor for CNP but we assume this equals merchant date_format(p.captured_at, '%Y-%m-01') as start_of_month, if( p.card_brand = 'Visa' or p.card_brand = 'MasterCard', p.card_brand, 'Other' ) as network, count(*) as sales_count, -- For US, both Cross-Border and Domestic charges are counted -- we can ignore this in CBMP but show it here just to get a magnitude count_if(p.card_country != 'US') as sales_count_crossborder, count_if(pmd.card_3ds_succeeded) as sales_count_3ds, sum(p.amount / fx.rate / 100.0) as sales_volume_usd, sum( if( p.card_country != 'US', p.amount / fx.rate / 100.0 ) ) as sales_volume_crossborder_usd, sum( if( p.card_country = 'US' and pmd.card_3ds_succeeded, p.amount / fx.rate / 100.0 ) ) as sales_volume_3ds_us_usd from charges p join exchange_rates fx on p.currency = fx.currency left join payment_method_details pmd on pmd.charge_id = p.id -- for more information you may use -- left join authentication_report_attempts aa on attempt_id intent_id where p.captured_at >= date_trunc('month', current_date - interval '150' day) -- CBMPs only consider cleared amounts; refunds still count in the volume unless reversed and p.status = 'succeeded' and p.payment_method_type = 'card' group by 1, 2 -- used for VFMP ), efw as ( select date_format(e.created, '%Y-%m-01') as start_of_month, if( c.card_brand = 'Visa' or c.card_brand = 'MasterCard', c.card_brand, 'Other' ) as network, -- For US, both Cross-Border and Domestic charges are counted -- count_if(card_country != 'US') as efw_count_crossborder count(distinct c.id) as efw_count, count(distinct if(pmd.card_3ds_succeeded, c.id)) as efw_count_3ds, sum(c.amount / fx.rate / 100.0) as efw_volume_usd, sum( if( pmd.card_3ds_succeeded, c.amount / fx.rate / 100.0 ) ) as efw_volume_3ds_usd, -- for VFMP-3DS sum( if( c.card_country = 'US' and pmd.card_3ds_succeeded, c.amount / fx.rate / 100.0 ) ) as efw_volume_3ds_us_usd from early_fraud_warnings e join charges c on e.charge_id = c.id join exchange_rates fx on c.currency = fx.currency left join payment_method_details pmd on pmd.charge_id = c.id where e.created >= date_trunc('month', current_date - interval '150' day) group by 1, 2 -- used for VDMP and ECM/ECP ), disputes as ( select date_format(d.created, '%Y-%m-01') as start_of_month, if( c.card_brand = 'Visa' or c.card_brand = 'MasterCard', c.card_brand, 'Other' ) as network, -- For US, both Cross-Border and Domestic charges are counted -- count_if(card_country != 'US') as dispute_count_crossborder -- Because a payment can have multiple disputes, we count the disputes here count(distinct d.id) as dispute_count_all, count(distinct if(d.reason = 'fraudulent', d.id)) as fraud_dispute_count_all, count( distinct if( d.network_details_visa_rapid_dispute_resolution, d.id ) ) as dispute_count_rdr, count( distinct if( d.network_details_visa_rapid_dispute_resolution is null or not d.network_details_visa_rapid_dispute_resolution, d.id ) ) as dispute_count_exrdr, count(distinct if(pmd.card_3ds_succeeded, d.id)) as dispute_count_3ds, count( distinct if( d.reason = 'fraudulent' and pmd.card_3ds_succeeded, d.id ) ) as fraud_dispute_count_3ds, count( distinct if( d.reason = 'fraudulent' and ( d.network_details_visa_rapid_dispute_resolution is null or not d.network_details_visa_rapid_dispute_resolution ), d.id ) ) as fraud_dispute_count_exrdr, count_if(d.status = 'won') * 1.0 / count_if( d.status = 'won' or d.status = 'lost' ) as win_rate, -- The sum of disputes should match and cannot exceed the payment sum(d.amount / fx.rate / 100.0) as dispute_volume_usd_all, sum( if( reason = 'fraudulent', d.amount / fx.rate / 100.0 ) ) as fraud_dispute_volume_usd_all, sum( if( ( d.network_details_visa_rapid_dispute_resolution is null or not d.network_details_visa_rapid_dispute_resolution ), d.amount / fx.rate / 100.0 ) ) as dispute_volume_usd_exrdr, sum( if( d.reason = 'fraudulent' and ( d.network_details_visa_rapid_dispute_resolution is null or not d.network_details_visa_rapid_dispute_resolution ), d.amount / fx.rate / 100.0 ) ) as fraud_dispute_volume_usd_exrdr from disputes d join charges c on d.charge_id = c.id join exchange_rates fx on c.currency = fx.currency left join payment_method_details pmd on pmd.charge_id = c.id where -- current month data will usually be off due to dispute delays, -- we still show it as an indicator but it's better tracked weekly d.created >= date_trunc('month', current_date - interval '150' day) group by 1, 2 ) select -- theoretically this might cause gaps if there is a month -- without payments but a helper table with continuous dates would complicate this example query p.start_of_month, p.network, -- Used for VDMP/ECP/ECM/HEC p.sales_count, lag(p.sales_count, 1) over ( order by p.network, p.start_of_month ) as sales_count_prior_month, p.sales_count_crossborder, p.sales_count_3ds, -- Used for VFMP p.sales_volume_usd, p.sales_volume_crossborder_usd, p.sales_volume_3ds_us_usd, e.efw_count, e.efw_count_3ds, -- Used for VFMP e.efw_volume_usd, e.efw_volume_3ds_usd, -- Used for VFMP-3DS e.efw_volume_3ds_us_usd, -- Used for VDMP/ECP/ECM/HEC d.dispute_count_all, d.dispute_count_rdr, d.fraud_dispute_count_all, d.dispute_count_exrdr, d.dispute_count_3ds, d.fraud_dispute_count_3ds, d.fraud_dispute_count_exrdr, d.dispute_volume_usd_all, -- Used for EFM d.fraud_dispute_volume_usd_all, d.dispute_volume_usd_exrdr, d.fraud_dispute_volume_usd_exrdr, d.win_rate, -- we show all the values below for all networks for comparison but they are only relevant for the indicated ones -- VDMP deducting RDR actuals if( p.network = 'visa', d.dispute_count_exrdr, d.dispute_count_all ) * 1.0 / p.sales_count as rdr_chargeback_ratio_for_visa, -- ECP/ECM/HECM based on prior month sales d.dispute_count_all * 1.0 / lag(p.sales_count, 1) over ( order by p.network, p.start_of_month ) as all_chargeback_ratio_for_mastercard, -- VDMP ignoring RDR and ECP/ECM/HECM for crosscheck d.dispute_count_all * 1.0 / p.sales_count as all_chargeback_ratio_for_visa_and_mastercard, -- VFMP e.efw_volume_usd * 1.0 / p.sales_volume_usd as fraud_ratio_for_visa, -- VFMP-3DS e.efw_volume_3ds_us_usd * 1.0 / p.sales_volume_3ds_us_usd as fraud_ratio_for_visa_3ds, -- EFM based on prior month sales d.fraud_dispute_count_all * 1.0 / lag(p.sales_count, 1) over ( order by p.network, p.start_of_month ) as fraud_ratio_for_mastercard from payments p left join efw e on p.start_of_month = e.start_of_month and p.network = e.network left join disputes d on p.start_of_month = d.start_of_month and p.network = d.network order by start_of_month desc, network;