Last active
December 24, 2015 12:19
-
-
Save deanpcmad/6796934 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require 'vendor/autoload.php'; | |
/** | |
* Configuration | |
*/ | |
$CONFIG = [ | |
'timezone' => 'Europe/London', | |
'stripe' => [ | |
'secret_key' => '-' | |
], | |
'freeagent' => [ | |
// OAuth keys, found in the FreeAgent developer dashboard once an app is created | |
'client_id' => '-', | |
'client_secret' => '-', | |
// Your OAuth refresh token. To generate this see here: | |
// https://dev.freeagent.com/docs/quick_start | |
// Remember to replace the sandbox API URL's with the proper ones. | |
// Once you follow instructions at that page, you should be able to find your | |
// refresh token in Google's OAuth Playground. | |
'refresh_token' => '-', | |
// Bank ID numbers as shown in query string when viewing bank account in FA. | |
// This saves an extra API call where we'd only be search and guessing the bank accounts anyway. | |
'bank_ids' => [ | |
'stripe' => '-', | |
'current' => '-' | |
] | |
] | |
]; | |
/** | |
* Time Periods | |
* Decide which time periods we're processing on this run | |
*/ | |
date_default_timezone_set($CONFIG['timezone']); | |
$time_start = new DateTime('June 2013 00:00:00'); | |
$time_end = new DateTime('yesterday 23:59:59'); | |
echo '---------------------------------------------' .PHP_EOL; | |
echo 'Transactions from: ' . $time_start->format('c') . PHP_EOL; | |
echo 'Transactions until: ' . $time_end->format('c') .PHP_EOL; | |
echo '---------------------------------------------' .PHP_EOL; | |
/** | |
* Fetch Stripe Transactions | |
* Make the API request to fetch Stripe's transactions recursively | |
* Fetches $fetchEachRun events at a time until less than $fetchEachRun events is returned | |
*/ | |
$stripeTransactions = []; | |
$fetchEachRun = 100; | |
$fetchOffset = 0; | |
Stripe::setApiKey($CONFIG['stripe']['secret_key']); | |
do { | |
$apiCall = Stripe_BalanceTransaction::all([ | |
'count' => $fetchEachRun, | |
'offset' => $fetchOffset, | |
'created' => [ | |
'gte' => $time_start->format('U'), | |
'lte' => $time_end->format('U') | |
] | |
]); | |
$fetchOffset += $fetchEachRun; | |
$stripeTransactions = array_merge($stripeTransactions, $apiCall->data); | |
echo 'Found ' . count($apiCall->data) . ' transactions at Stripe...' . PHP_EOL; | |
} while(count($apiCall->data) >= $fetchEachRun); | |
echo 'Found ' . number_format(count($stripeTransactions)) . ' total transactions at Stripe.' . PHP_EOL; | |
if(!count($stripeTransactions)) { | |
die('[ERROR] No events to move into FreeAgent! Exiting.' . PHP_EOL); | |
} | |
/** | |
* Generate CSV | |
* Walk through each Stripe event and add the event into our bank upload CSV | |
*/ | |
echo 'Building the CSV file to be uploaded as a bank statement...' . PHP_EOL; | |
$csv = []; | |
foreach($stripeTransactions AS $transaction) { | |
// Decide which date we're going to use for this transaction | |
if($transaction->type == 'transfer') { | |
$time = $transaction->available_on; | |
} else { | |
$time = $transaction->created; | |
} | |
$date = DateTime::createFromFormat('U', $time)->format('d/m/Y'); | |
// Turn the amount into pounds from pennies | |
$amount = $transaction->amount / 100; | |
// Create a meaningful description | |
if(empty($transaction->description)) { | |
$description = 'No Description'; | |
} else { | |
$description = str_replace(['\'', '"', ','], '_', ucwords(strtolower($transaction->description))); | |
} | |
$description = sprintf('%s - %s [%s]', ucwords($transaction->type), $description, $transaction->id); | |
// Add this line to the CSV | |
$csv[] = [$date, $amount, $description]; | |
// Record any fees for this transaction | |
if($transaction->fee != 0) { | |
// Turn the fee amount into whole points and reverse it | |
// E.g. a fee of £1.00 should show as £-1.00 from the FA Stripe account balance | |
$fee_amount = 0 - ($transaction->fee / 100); | |
// Describe this fee, based on the description above | |
if($fee_amount > 0) { | |
$fee_description = 'Fee Refund'; | |
} else { | |
$fee_description = 'Fee'; | |
} | |
$fee_description .= substr($description, strpos($description, '-') - 1); | |
// Add this fee as a line to the CSV | |
$csv[] = [$date, $fee_amount, $fee_description]; | |
} | |
} | |
// Turn the CSV data into a valid format to be uploaded | |
$csv = implode(PHP_EOL, array_map(function($row) { | |
return implode(',', $row); | |
}, $csv)); | |
// It's nice to keep an eye on things and see the CSV being generated | |
echo '---------------------------------------------' . PHP_EOL; | |
echo $csv . PHP_EOL; | |
echo '---------------------------------------------' . PHP_EOL; | |
/** | |
* Setup OAuth for FreeAgent | |
*/ | |
$faOauth = new OAuth2\Client($CONFIG['freeagent']['client_id'], $CONFIG['freeagent']['client_secret']); | |
// Grab a fresh access token using our permanent refresh token | |
$faOauth->setAccessTokenType(OAuth2\Client::ACCESS_TOKEN_BEARER); | |
$response = $faOauth->getAccessToken('https://api.freeagent.com/v2/token_endpoint', 'refresh_token', ['refresh_token' => $CONFIG['freeagent']['refresh_token']]); | |
// Tell the oauth client library to use our fresh access token | |
$faOauth->setAccessToken($response['result']['access_token']); | |
/** | |
* Upload to FreeAgent | |
*/ | |
$response = $faOauth->fetch( | |
sprintf('https://api.freeagent.com/v2/bank_transactions/statement?bank_account=%d', $CONFIG['freeagent']['bank_ids']['stripe']), | |
['statement' => $csv], | |
'POST', | |
['User-Agent' => 'N/A'] | |
); | |
if($response['code'] != 200) { | |
echo '[ERROR] There was a problem with the FreeAgent API when making the statement upload.' . PHP_EOL; | |
echo '[API Error] ' . $response['result']['errors']['error']['message'] . PHP_EOL; | |
exit; | |
} | |
echo 'The CSV statement has been uploaded to FreeAgent.' . PHP_EOL; | |
/** | |
* Make explanations at FreeAgent | |
*/ | |
$freeagentUnexplained = []; | |
$fetchEachRun = 100; | |
$fetchPage = 1; | |
do { | |
$response = $faOauth->fetch( | |
'https://api.freeagent.com/v2/bank_transactions', | |
[ | |
'bank_account' => $CONFIG['freeagent']['bank_ids']['stripe'], | |
'view' => 'unexplained', | |
'per_page' => $fetchEachRun, | |
'page' => $fetchPage | |
], | |
'GET', | |
[ | |
'User-Agent' => 'N/A', | |
'Content-Type' => 'application/json', | |
] | |
); | |
if($response['code'] != 200) { | |
echo '[ERROR] There was a problem with the FreeAgent API when fetching unexplained bank transactions.' . PHP_EOL; | |
// echo '[API Error] ' . $response['result']['errors']['error']['message'] . PHP_EOL; | |
exit; | |
} | |
$results = $response['result']['bank_transactions']; | |
$freeagentUnexplained = array_merge($freeagentUnexplained, $results); | |
$fetchPage++; | |
echo 'Found ' . count($results) . ' unexplained transactions in the Stripe account at FreeAgent...' . PHP_EOL; | |
} while(count($results) >= $fetchEachRun); | |
echo 'Found ' . number_format(count($freeagentUnexplained)) . ' total unexplained transactions in the Stripe account at FreeAgent.' . PHP_EOL; | |
foreach($freeagentUnexplained AS $transaction) { | |
$faTxnId = substr($transaction['url'], strrpos($transaction['url'], '/') + 1); | |
$faTxnType = strtolower(str_replace(' ', '_', substr($transaction['description'], 0, strpos($transaction['description'], '-') - 1))); | |
// Decide what we need to explain this particular transaction as | |
$data = [ | |
]; | |
if($faTxnType == 'transfer') { | |
$data['transfer_bank_account'] = $CONFIG['freeagent']['bank_ids']['current']; | |
} | |
if(stristr($transaction['description'], 'Fee')) | |
{ | |
$data['category'] = "363"; | |
$data['description'] = 'Stripe charge'; | |
} | |
else | |
{ | |
$data['category'] = "001"; | |
// Removes the crap and leaves "Invoice #123" as the description | |
preg_match("/Invoice #[0-9]*/i", $transaction['description'], $output); | |
$data['description'] = $output[0]; | |
} | |
// Try to explain this transaction at FreeAgent | |
printf('Explaining FreeAgent bank transaction %d [%s]...', $faTxnId, $faTxnType); | |
$response = $faOauth->fetch( | |
'https://api.freeagent.com/v2/bank_transaction_explanations', | |
json_encode([ | |
'bank_transaction_explanation' => array_merge([ | |
'bank_transaction' => $transaction['url'], | |
'dated_on' => $transaction['dated_on'], | |
'gross_value' => $transaction['amount'], | |
'description' => $transaction['description'], | |
], $data), | |
]), | |
'POST', | |
[ | |
'User-Agent' => 'N/A', | |
'Content-Type' => 'application/json', | |
] | |
); | |
if($response['code'] == 200 || 201) { | |
echo 'OK.' . PHP_EOL; | |
} else { | |
echo 'FAILED.' . PHP_EOL; | |
var_dump($response['result']) . PHP_EOL; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment