/stripe-guides

How to check fraud risk in Stripe payments?

Learn how to check fraud risk in Stripe payments using Stripe Radar, custom rules, webhooks, and best practices to protect your business from online payment fraud.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to check fraud risk in Stripe payments?

How to Check Fraud Risk in Stripe Payments: A Comprehensive Guide

 

Introduction

 

Preventing fraud is crucial when processing online payments. Stripe offers robust tools to help merchants identify and mitigate fraud risks. This tutorial provides a detailed walkthrough of implementing fraud detection in your Stripe integration.

 

Step 1: Set Up Your Stripe Account

 

Before implementing fraud detection, ensure you have a Stripe account properly configured:

  1. Sign up for a Stripe account at https://stripe.com/
  2. Complete the verification process
  3. Obtain your API keys from the Dashboard

 

Step 2: Install the Stripe Library

 

First, you need to install the Stripe library for your programming language:

For Node.js:

npm install stripe

For Python:

pip install stripe

For PHP:

composer require stripe/stripe-php

 

Step 3: Initialize the Stripe Client

 

Set up the Stripe client with your API keys:

For Node.js:

const stripe = require('stripe')('sk_test_your_secret_key');

// For better security, load the key from environment variables
// const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

For Python:

import stripe
stripe.api_key = "sk_test_your_secret\_key"

# Better practice using environment variables
# import os
# stripe.api_key = os.environ.get('STRIPE_SECRET\_KEY')

For PHP:

\Stripe\Stripe::setApiKey('sk_test_your_secret_key');

// Better security using environment variables
// \Stripe\Stripe::setApiKey(getenv('STRIPE_SECRET_KEY'));

 

Step 4: Implement Radar for Fraud Detection

 

Stripe Radar is Stripe's built-in fraud detection system. Here's how to use it:

  1. Enable Radar in your Stripe Dashboard (automatically enabled for most accounts)
  2. Access Radar settings at Dashboard > Radar > Rules
  3. Review and customize default rules for your business needs

 

Step 5: Check the Radar Risk Score During Payment Processing

 

When processing payments, you can check the risk level:

For Node.js:

async function createPaymentIntent(amount, currency) {
  try {
    const paymentIntent = await stripe.paymentIntents.create({
      amount: amount,
      currency: currency,
    });
    
    // Retrieve the payment intent to check risk score
    const retrievedIntent = await stripe.paymentIntents.retrieve(
      paymentIntent.id
    );
    
    // Check risk score if available
    if (retrievedIntent.charges && retrievedIntent.charges.data.length > 0) {
      const riskScore = retrievedIntent.charges.data[0].outcome.risk\_score;
      const riskLevel = retrievedIntent.charges.data[0].outcome.risk\_level;
      console.log(`Risk Score: ${riskScore}, Risk Level: ${riskLevel}`);
      
      // Take action based on risk level
      if (riskLevel === 'elevated' || riskLevel === 'highest') {
        // Consider additional verification steps
        console.log('High risk payment detected. Additional verification recommended.');
      }
    }
    
    return paymentIntent;
  } catch (error) {
    console.error('Error creating payment intent:', error);
    throw error;
  }
}

For Python:

def create_payment_intent(amount, currency):
    try:
        payment\_intent = stripe.PaymentIntent.create(
            amount=amount,
            currency=currency,
        )
        
        # Retrieve the payment intent to check risk score
        retrieved_intent = stripe.PaymentIntent.retrieve(payment_intent.id)
        
        # Check risk score if available
        if retrieved_intent.charges and len(retrieved_intent.charges.data) > 0:
            risk_score = retrieved_intent.charges.data[0].outcome.risk\_score
            risk_level = retrieved_intent.charges.data[0].outcome.risk\_level
            print(f"Risk Score: {risk_score}, Risk Level: {risk_level}")
            
            # Take action based on risk level
            if risk\_level in ['elevated', 'highest']:
                # Consider additional verification steps
                print('High risk payment detected. Additional verification recommended.')
        
        return payment\_intent
    except Exception as e:
        print(f"Error creating payment intent: {str(e)}")
        raise e

 

Step 6: Check Fraud Risk in Payment Webhooks

 

Set up webhooks to receive real-time fraud assessments:

For Node.js (using Express):

const express = require('express');
const app = express();

// You need the raw request body for signature verification
app.use('/webhook', express.raw({type: 'application/json'}));

app.post('/webhook', async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      'whsec_your_webhook_signing_secret'
    );
  } catch (err) {
    console.log(`Webhook Error: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Handle successful charges
  if (event.type === 'charge.succeeded') {
    const charge = event.data.object;
    
    // Check for fraud indicators
    const outcome = charge.outcome;
    if (outcome) {
      console.log(`Risk Level: ${outcome.risk_level}`);
      console.log(`Risk Score: ${outcome.risk_score}`);
      console.log(`Seller Message: ${outcome.seller_message}`);
      
      // Take appropriate actions based on risk assessment
      if (outcome.risk_level === 'elevated' || outcome.risk_level === 'highest') {
        // Log high-risk transactions
        console.log(`High risk transaction detected: ${charge.id}`);
        
        // Optionally flag for review or additional verification
        // await flagTransactionForReview(charge.id);
      }
    }
  }

  res.json({received: true});
});

For Python (using Flask):

from flask import Flask, request, jsonify
import stripe

app = Flask(**name**)

@app.route('/webhook', methods=['POST'])
def webhook():
    payload = request.data
    sig\_header = request.headers.get('Stripe-Signature')
    
    try:
        event = stripe.Webhook.construct\_event(
            payload, sig_header, 'whsec_your_webhook_signing\_secret'
        )
    except ValueError as e:
        # Invalid payload
        return jsonify(error=str(e)), 400
    except stripe.error.SignatureVerificationError as e:
        # Invalid signature
        return jsonify(error=str(e)), 400
    
    # Handle successful charges
    if event['type'] == 'charge.succeeded':
        charge = event\['data']\['object']
        
        # Check for fraud indicators
        outcome = charge.get('outcome', {})
        if outcome:
            print(f"Risk Level: {outcome.get('risk\_level')}")
            print(f"Risk Score: {outcome.get('risk\_score')}")
            print(f"Seller Message: {outcome.get('seller\_message')}")
            
            # Take appropriate actions based on risk assessment
            if outcome.get('risk\_level') in ['elevated', 'highest']:
                # Log high-risk transactions
                print(f"High risk transaction detected: {charge['id']}")
                
                # Optionally flag for review or additional verification
                # flag_transaction_for\_review(charge['id'])
    
    return jsonify(success=True)

 

Step 7: Create Custom Radar Rules

 

You can create custom rules in the Stripe Dashboard:

  1. Navigate to Dashboard > Radar > Rules
  2. Click "Create rule"
  3. Define conditions using Stripe's rule language

Example rule syntax:

:card_country: = 'US' AND :ip_country: != 'US'

This rule identifies transactions where the card is from the US but the IP address is not.

 

Step 8: Implement Advanced Fraud Detection with Additional Data

 

Send additional data to Stripe to improve fraud detection:

For Node.js:

// When creating a PaymentIntent
const paymentIntent = await stripe.paymentIntents.create({
  amount: 2000,
  currency: 'usd',
  payment_method_types: ['card'],
  // Additional data for fraud detection
  metadata: {
    order\_id: '6735',
    customer\_id: '1234'
  }
});

// When using Checkout Session
const session = await stripe.checkout.sessions.create({
  payment_method_types: ['card'],
  line\_items: [{
    price\_data: {
      currency: 'usd',
      product\_data: {
        name: 'T-shirt',
      },
      unit\_amount: 2000,
    },
    quantity: 1,
  }],
  mode: 'payment',
  success\_url: 'https://example.com/success',
  cancel\_url: 'https://example.com/cancel',
  // Additional data for fraud detection
  customer\_email: '[email protected]',
  metadata: {
    order\_id: '6735'
  },
  payment_intent_data: {
    description: 'Purchase of t-shirt',
    metadata: {
      order\_id: '6735'
    },
    shipping: {
      name: 'Jenny Rosen',
      address: {
        line1: '123 Main St',
        city: 'San Francisco',
        state: 'CA',
        postal\_code: '94111',
        country: 'US',
      },
    },
  },
});

 

Step 9: Set Up Fraud Alerts and Notifications

 

Configure alerts for high-risk transactions:

  1. Go to Dashboard > Settings > Email Notifications
  2. Enable notifications for "High-risk payments"
  3. Alternatively, implement custom notifications through webhooks

Custom webhook notification example (Node.js):

// In your webhook handler
if (event.type === 'charge.succeeded') {
  const charge = event.data.object;
  
  if (charge.outcome && charge.outcome.risk\_level === 'highest') {
    // Send notification to your internal systems
    await sendHighRiskAlert({
      chargeId: charge.id,
      amount: charge.amount,
      currency: charge.currency,
      riskScore: charge.outcome.risk\_score,
      customerEmail: charge.billing\_details.email
    });
  }
}

 

Step 10: Monitor and Review Fraud Patterns

 

Regularly review and analyze fraud patterns:

  1. Check the Stripe Dashboard > Radar > Overview for fraud metrics
  2. Review blocked payments in Dashboard > Radar > Reviews
  3. Analyze patterns and adjust rules as needed

Example code to fetch blocked payments for analysis (Node.js):

async function getBlockedPayments() {
  try {
    const charges = await stripe.charges.list({
      limit: 100,
    });
    
    // Filter blocked or high-risk charges
    const blockedOrHighRisk = charges.data.filter(charge => {
      if (!charge.outcome) return false;
      return charge.outcome.type === 'blocked' || 
             charge.outcome.risk\_level === 'highest' ||
             charge.outcome.risk\_level === 'elevated';
    });
    
    // Analyze patterns
    const countryFrequency = {};
    const ipFrequency = {};
    
    blockedOrHighRisk.forEach(charge => {
      // Count card countries
      const country = charge.payment_method_details?.card?.country || 'unknown';
      countryFrequency[country] = (countryFrequency[country] || 0) + 1;
      
      // Count IP addresses if available
      if (charge.metadata && charge.metadata.ip\_address) {
        const ip = charge.metadata.ip\_address;
        ipFrequency[ip] = (ipFrequency[ip] || 0) + 1;
      }
    });
    
    return {
      blockedOrHighRisk,
      countryFrequency,
      ipFrequency
    };
  } catch (error) {
    console.error('Error fetching blocked payments:', error);
    throw error;
  }
}

 

Conclusion

 

Implementing proper fraud detection with Stripe Radar can significantly reduce your risk exposure. This tutorial covered the essential steps to configure, implement, and monitor fraud detection in your Stripe integration. Remember to regularly review your fraud prevention strategy and adjust it based on emerging patterns and your business needs.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022