Created
February 17, 2018 08:17
-
-
Save dansleboby/0abad06069a34fe8902e26e971511065 to your computer and use it in GitHub Desktop.
Little script to sync camscanner with Invoice Ninja Expenses
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 | |
/* | |
Little script to sync camscanner with Invoice Ninja Expenses | |
-> How to use <- | |
1. create composer.json and run an update to get curl helper | |
2. Set 2 variables of invoice ninja | |
3. run php index.php | |
4. You will get an url https://api.intsig.net/qr_login/image?qrl_id=XXXXXXXXXXXXXXXX you need to open this in browser and scan with app to login in script | |
5. Enjoy! | |
-> Camscanner naming convention <- | |
YYYY-MM-DD_Vendor name_Amount_method payment | |
Ex: 2018-02-17_Wal-Mart_125.25_visa | |
This will add Wal-Mart as vendor if not exists and save the details of payments and attach pictures. | |
For payments method please update $payments_type there no api to fetch | |
-> Help <- | |
Just comment I will do my best to answer :) | |
composer.json | |
{ | |
"require": { | |
"mervick/curl-helper": "^1.1" | |
} | |
} | |
*/ | |
require "vendor/autoload.php"; | |
$invoiceninja_api = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";//base path of invoiceninja self-hosted or sub-domain of hosted solution | |
$invoiceninja_token = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";//Api token | |
//Billing | |
echo "Fetch expenses...\n"; | |
$response = CurlHelper::factory("https://$invoiceninja_api/api/v1/expenses?per_page=500") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest', 'X-Ninja-Token' => $invoiceninja_token]) | |
->exec(); | |
$expenses = []; | |
foreach($response['data']['data'] as $data) | |
$expenses[] = $data['private_notes']; | |
echo "Fetch vendors...\n"; | |
$response = CurlHelper::factory("https://$invoiceninja_api/api/v1/vendors?per_page=500") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest', 'X-Ninja-Token' => $invoiceninja_token]) | |
->exec(); | |
$vendors = []; | |
foreach($response['data']['data'] as $data) | |
$vendors[$data['id']] = $data['name']; | |
echo "Fetch expenses cat....\n"; | |
$response = CurlHelper::factory("https://$invoiceninja_api/api/v1/expense_categories?per_page=500") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest', 'X-Ninja-Token' => $invoiceninja_token]) | |
->exec(); | |
$expense_categories = []; | |
foreach($response['data']['data'] as $data) | |
$expense_categories[$data['id']] = $data['name']; | |
echo "Payments type...\n"; | |
$payments_type = [6 => 'visa', 3 => 'cash', 14 => 'Paypal']; | |
//Because I am lasy | |
echo "Flip...\n"; | |
$vendors = array_flip($vendors); | |
$expense_categories = array_flip($expense_categories); | |
$payments_type = array_flip($payments_type); | |
function addExpenses($data) { | |
global $vendors, $expense_categories, $payments_type; | |
if(!array_key_exists($data['vendor_name'], $vendors)) { | |
//Create Vendors if not exists | |
$response = CurlHelper::factory("https://$invoiceninja_api/api/v1/vendors") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest', 'X-Ninja-Token' => $invoiceninja_token, 'Content-Type' => CurlHelper::MIME_X_WWW_FORM]) | |
->setPostFields([ | |
'name' => $data['vendor_name'] | |
]) | |
->exec(); | |
$vendors[$data['vendor_name']] = $response['data']['data']['id']; | |
} | |
$vendor_id = $vendors[$data['vendor_name']]; | |
$vendor_name = $data['vendor_name']; | |
if(!array_key_exists($data['expense_categories_name'], $expense_categories)) { | |
//Create expense_categories if not exits | |
$response = CurlHelper::factory("https://$invoiceninja_api/api/v1/expense_categories") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest', 'X-Ninja-Token' => $invoiceninja_token, 'Content-Type' => CurlHelper::MIME_X_WWW_FORM]) | |
->setPostFields([ | |
'name' => $data['expense_categories_name'] | |
]) | |
->exec(); | |
$expense_categories[$data['expense_categories_name']] = $response['data']['data']['id']; | |
} | |
$expense_categories_id = $expense_categories[$data['expense_categories_name']]; | |
$expense_categories_name = $data['expense_categories_name']; | |
$response = CurlHelper::factory("https://$invoiceninja_api/api/v1/expenses") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest', 'X-Ninja-Token' => $invoiceninja_token, 'Content-Type' => CurlHelper::MIME_X_WWW_FORM]) | |
->setPostFields([ | |
'vendor_id' => $vendor_id, | |
'vendor_name' => $vendor_name, | |
'expense_category_id' => $expense_categories_id, | |
'expense_category_name' => $expense_categories_name, | |
'amount' => $data['amount'], | |
'expense_date' => $data['date'], | |
'should_be_invoiced' => '0', | |
'mark_paid' => '1', | |
'payment_type_id' => $payments_type[$data['payment']], | |
'payment_date' => $data['date'], | |
'invoice_documents' => '0', | |
'private_notes' => $data['id'] | |
]) | |
->exec(); | |
$expense_id = $response['data']['data']['id']; | |
foreach($data['files'] as $file) { | |
$response = CurlHelper::factory("https://$invoiceninja_api/api/v1/documents") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest', 'X-Ninja-Token' => $invoiceninja_token, 'Content-Type' => CurlHelper::MIME_FORM_DATA]) | |
->setPostFields([ | |
'expense_id' => $expense_id, | |
'name' => $file['name'], | |
'type' => $file['type'] | |
]) | |
->putFile('file', $file['path']) | |
->exec(); | |
$document_id = $response['data']['data']['id']; | |
} | |
return is_numeric($expense_id) && is_numeric($document_id); | |
} | |
//Get login QR | |
$response = CurlHelper::factory("https://www.camscanner.com/user/qrlogin_init") | |
->setCookieFile('cookies.txt') | |
->exec(); | |
$qrl_id = json_decode($response['data']['data'])->qrl_id; | |
echo "https://api.intsig.net/qr_login/image?qrl_id=$qrl_id\n"; | |
//Check if QR was scanned | |
echo "CHECK...\n"; | |
do { | |
echo "."; | |
$response = CurlHelper::factory("https://www.camscanner.com/user/qrlogin_query?qrl_id=$qrl_id") | |
->setCookieFile('cookies.txt') | |
->exec(); | |
$data = json_decode($response['data']['data']); | |
if(property_exists($data, 'token')) { | |
$token = $data->token; | |
echo "\nGrep token\n"; | |
} | |
sleep(1); | |
} while ($data->status != 3); | |
//Make login with token | |
echo "\nLogin... [$token]\n"; | |
$response = CurlHelper::factory("https://www.camscanner.com/user/login") | |
->setHeaders(['Content-Type' => CurlHelper::MIME_X_WWW_FORM, 'X-Requested-With' => 'XMLHttpRequest']) | |
->setPostFields(['token' => $token, 'act' => 'submit', 'type' => 'qrlogin']) | |
->setCookieFile('cookies.txt') | |
->exec(); | |
if(!empty($response['data'])) { | |
echo "Data...\n"; | |
$response = CurlHelper::factory("https://www.camscanner.com/doc/list") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest']) | |
->setCookieFile('cookies.txt') | |
->exec(); | |
$files = $response['data']['data']['list']; | |
$server = $response['data']['data']['server']; | |
$data = []; | |
foreach($files as $file) { | |
if(in_array($file['doc_id'], $expenses)) { | |
echo "Already in DB...\n"; | |
continue; | |
} | |
$tmp = []; | |
if(preg_match("#^[0-9]{4}-[0-9]{2}-[0-9]{2}.*#", $file['title']) && isset($file['tag'])) { | |
$parse = explode('_', $file['title']); | |
if(count($parse) == 4) | |
list($date, $vendor_name, $amount, $type) = $parse; | |
else if(count($parse) == 3){ | |
list($date, $vendor_name, $amount) = $parse; | |
$type = 'visa'; | |
} else { | |
echo "ERROR PARSE: ".$file['title']."\n"; | |
continue; | |
} | |
$expense_categories_name = $file['tag']; | |
$tmp = [ | |
'id' => $file['doc_id'], | |
'expense_categories_name' => $expense_categories_name, | |
'vendor_name' => $vendor_name, | |
'amount' => $amount, | |
'payment' => $type, | |
'date' => $date, | |
'files' => [], | |
]; | |
if($file['c'] > 1) { | |
//Need to fetch | |
echo "Fetch page...\n"; | |
$response = CurlHelper::factory("https://www.camscanner.com/doc/pagelist") | |
->setHeaders(['X-Requested-With' => 'XMLHttpRequest']) | |
->setPostFields(['doc_id' => $tmp['id']]) | |
->setCookieFile('cookies.txt') | |
->exec(); | |
$pages = $response['data']['data']; | |
foreach($pages as $page) { | |
if(!file_exists($page['page_id'].".jpg")) { | |
echo "Down :".$page['page_id']."\n"; | |
$response = CurlHelper::factory($page['page_photo']) | |
->setCookieFile('cookies.txt') | |
->exec(); | |
file_put_contents($page['page_id'].".jpg", $response['content']); | |
} else { | |
echo "File exists: ".$page['page_id'].".jpg\n"; | |
} | |
$tmp['files'][] = ['name' => $page['page_id'].".jpg", 'type' => 'jpg', 'path' => $page['page_id'].".jpg"]; | |
} | |
} else { | |
if(!file_exists($file['p'].'.jpg')) { | |
echo "Down :".$file['p']."\n"; | |
$response = CurlHelper::factory($server.$file['p'].'.jpg') | |
->setCookieFile('cookies.txt') | |
->exec(); | |
file_put_contents($file['p'].'.jpg', $response['content']); | |
} else { | |
echo "File exists: ".$file['p'].'.jpg'."\n"; | |
} | |
$tmp['files'][0] = ['name' => $file['p'].'.jpg', 'type' => 'jpg', 'path' => $file['p'].'.jpg']; | |
} | |
echo "Push to billing...\n"; | |
$res = addExpenses($tmp); | |
if($res) { | |
echo "Success\n"; | |
} else { | |
echo "Failed\n"; | |
print_r($tmp); | |
print_r($file); | |
die(); | |
} | |
} else { | |
/*echo "\n\n\n!!! ERROR !!!!\n"; | |
print_r($file); | |
echo "\n\n\n";*/ | |
echo "Error bad title: ".$file['title']."\n"; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment