Match Stripe customers to data in a CSV based on card metadata (last4, zip, etc). Useful when migrating card data to Stripe.
# Michael Bianco <mike@suitesync.io> | |
# NOTE tabs are used for easy copy/paste into google sheets | |
require 'stripe' | |
require 'csv' | |
require 'pry' | |
Stripe.api_key = 'sk_live_' | |
if ARGV.empty? | |
puts "No CSV path specified" | |
exit 1 | |
end | |
csv_path = ARGV.first | |
csv_mapping = CSV.read(csv_path, headers: true) | |
used_mappings = [] | |
dry_run = false | |
allow_multiple_sources = true | |
overwrite_description = true | |
# Mapping: | |
# | |
# - LastFour | |
# - ExpMonth | |
# - ExpYear. 2 digit. | |
# - Brand | |
# | |
# Map to: | |
# | |
# - Description | |
multiple_sources = [] | |
no_stripe_match = [] | |
Stripe::Customer.list(limit: 100).auto_paging_each do |customer| | |
if customer.sources.count > 1 && !allow_multiple_sources | |
multiple_sources << customer | |
puts "#{customer.id}\tcustomer has multiple payment sources" | |
next | |
end | |
if !customer.description.nil? && !customer.description.empty? && !overwrite_description | |
puts "#{customer.id}\tcustomer has description" | |
next | |
end | |
# find matching customer by: | |
# - last 4 | |
# - expiration (MM & YY) | |
# - zip? | |
stripe_card = customer.sources.first | |
last_four = stripe_card.last4 | |
zip = stripe_card.address_zip | |
brand = stripe_card.brand.strip.gsub(/[^a-zA-Z]*/, '').downcase | |
expiration_month = stripe_card.exp_month | |
expiration_year = stripe_card.exp_year - 2000 | |
csv_mapping.each_with_index do |row, i| | |
if row['Brand'].downcase.strip.gsub(/[^a-zA-Z]*/, '') == brand && | |
last_four == row['LastFour'] && | |
expiration_month == row['ExpMonth'].to_i && | |
expiration_year == row['ExpYear'].to_i | |
if used_mappings.include?(i) | |
puts "#{customer.id}\tmapping row #{i + 1}\tmapping is already used" | |
end | |
used_mappings << i | |
customer.description = row['Description'] | |
customer.email = row['Email'] | |
if !dry_run | |
customer.save | |
end | |
break | |
end | |
end | |
if customer.description.nil? | |
puts "#{customer.id}\tno match found" | |
end | |
end | |
puts "\nUnmatched CSV rows" | |
((0..(csv_mapping.count - 1)).to_a - used_mappings).each do |index| | |
puts csv_mapping[index].to_csv(col_sep: "\t") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment