How to Issue Bulk Refunds through the Stripe API

Today was not a good day.  In short, a nonprofit’s online donation form was hit 1,285 times in an attempt to validate stolen credit cards.  Unfortunately, 120 of those succeeded, meaning our Stripe account had over $600 in fraudulent donations.  I needed a quick way to fully refund those charges, but in bulk.  Through the Java API client, I was able to do the following.  I figured I’d throw it out here, in case someone else can use it.  Note that although it uses the Java  client, the concept is identical for others.

import com.stripe.Stripe;
import com.stripe.model.Charge;
import com.stripe.model.ChargeCollection;
 
import java.util.HashMap;
import java.util.Map;
 
public class StripeRefunder {
 
    public static void main(String[] args) {
        try {
            ////////////////////////////
            // USE YOUR STRIPE KEY HERE.
            Stripe.apiKey = "";
            ////////////////////////////
 
            int iterationCount = 100;
            String startAfter = null;
            int totalCount = 0;
            while (iterationCount >= 100) {
                ChargeCollection charges = get(startAfter);
                iterationCount = charges.getData().size();
                totalCount += iterationCount;
                startAfter = charges.getData().get(iterationCount - 1).getId();
            }
 
            System.out.println("TOTAL REFUNDS: " + totalCount);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    private static ChargeCollection get(String startAfter) throws Exception {
        Map<String, Object> params = new HashMap<String, Object>();
 
        ////////////////////////////////////////////////////////////////////////
        // USE RELEVANT LOGIC HERE.  IN OUR CASE, THE FRAUD CHARGES WERE ALL $5.
        params.put("paid", true);
        params.put("amount", 500);
        ////////////////////////////////////////////////////////////////////////
 
        params.put("limit", 100);
        if (startAfter != null) {
            params.put("starting_after", startAfter);
        }
        ChargeCollection charges = Charge.all(params);
        for (Charge charge : charges.getData()) {
            charge.refund();
        }
        return charges;
    }
}