Skip to content

Instantly share code, notes, and snippets.

@reinvented
Last active May 7, 2024 12:49
Show Gist options
  • Select an option

  • Save reinvented/22d173c7f0a607a7069ad7324b125f57 to your computer and use it in GitHub Desktop.

Select an option

Save reinvented/22d173c7f0a607a7069ad7324b125f57 to your computer and use it in GitHub Desktop.
Automating the use of Canada Revenue's Payroll Deductions Online Calculator in PHP
<?php
// This is a hack, designed for my specific set of circumstances (weekly salaried employees on PEI)
// So if you use it as the basis for your own calculations, you'll likely have to do some customizing.
$options = getopt("d:i:v:");
$param = array();
if (array_key_exists('d', $options)) {
list($param['year'], $param['month'], $param['day']) = explode("-", $options['d']);
$param['month'] = str_pad($param['month'], 2, '0', STR_PAD_LEFT);
$param['day'] = str_pad($param['day'], 2, '0', STR_PAD_LEFT);
}
if (array_key_exists('i', $options)) {
$param['income'] = $options['i'];
}
if (array_key_exists('v', $options)) {
$param['vacationPay'] = $options['v'];
}
$requiredParams = array('year' => '', 'month' => '', 'day' => '', 'income' => '', 'vacationPay' => '');
$missingParams = array_diff_key($requiredParams, $param);
if (count($missingParams)) {
die("Usage: get-pdoc.php -i [income] -v [vacation pay] -d [date]\n\n");
}
$data = array(
"step0" => array(
"calculationType" => "salary", // Salary
"goStep1" => "Next"
),
"step1" => array(
"employeeName" => "The Employee",
"employerName" => "The Employer",
"province" => "2", // Prince Edward Island
"payPeriod" => "1", // Weekly
"cmbFirstYear" => $param['year'],
"cmbFirstMonth" => $param['month'],
"cmbFirstDay" => $param['day'],
"goStep2AddOption" => "Next"
),
"step2" => array(
"incomeTypeAmount" => $param['income'],
"vacationPay" => $param['vacationPay'],
"salaryType" => "na",
"clergyType" => "hna",
"goStep2Option" => "Next"
),
"step3" => array(
"claimCodeFed" => "1",
"requestAdditionalTax" => "0.00",
"claimCodeProv" => "1",
"yearToDateCPP" => "0",
"yearToDatePeAmount" => "0",
"yearToDateCPPAmount" => "0",
"yearToDateEI" => "0",
"yearToDateIeAmount" => "0",
"yearToDateEIAmount" => "0",
"reducedEIRate" => "0",
"goResults" => "Calculate"
),
);
$triggers = array(
"federalTax" => array("Federal tax deduction", 2),
"provincialTax" => array("Provincial tax deduction", 4),
"CPP" => array("CPP deductions", 5),
"EI" => array("EI deductions", 3),
);
$result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/startLanguage.do?lang=English", array('post' => false));
$result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/handleEntryPoint.do", array('refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/startLanguage.do?lang=English', 'post' => http_build_query($data['step0'], '', '&')));
$result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/handleGeneralInfo.do", array('refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/handleEntryPoint.do', 'post' => http_build_query($data['step1'], '', '&')));
$result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/handleAdditionalOptions.do", array('refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/handleGeneralInfo.do', 'post' => http_build_query($data['step2'], '', '&')));
$result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/s-handleInterview.do", array('refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/handleAdditionalOptions.do', 'post' => http_build_query($data['step3'], '', '&')));
$lines = explode("\n", $result);
foreach ($lines as $linenumber => $line) {
foreach ($triggers as $key => $trigger) {
if (strpos($line, $trigger[0]) !== FALSE) {
$values[$key] = trim($lines[$linenumber + $trigger[1]]);
}
}
}
print_r($values);
function fetch( $url, $z=null ) {
$ch = curl_init();
$useragent = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2';
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_POST, isset($z['post']) );
if( isset($z['post']) ) curl_setopt( $ch, CURLOPT_POSTFIELDS, $z['post'] );
if( isset($z['refer']) ) curl_setopt( $ch, CURLOPT_REFERER, $z['refer'] );
curl_setopt( $ch, CURLOPT_USERAGENT, $useragent );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 5 );
curl_setopt( $ch, CURLOPT_COOKIEJAR, '/tmp/cra-cookies.txt' );
curl_setopt( $ch, CURLOPT_COOKIEFILE, '/tmp/cra-cookies.txt' );
$result = curl_exec( $ch );
curl_close( $ch );
return $result;
}
@educsis
Copy link

educsis commented Sep 22, 2019

I think it doesn't work anymore, great stuff by the way. I think that it now uses session cookies, because if your token doesn't match, it gives an error.

@Meekcanadian
Copy link

Does anyone know of other api for Canadian payroll?

@bluntcoder
Copy link

Does anyone know of other api for Canadian payroll?

I'm also looking as well!

@DianaLozanoP
Copy link

Me too, looking for an API.

@vynci
Copy link

vynci commented Feb 8, 2024

I'm planning to build a micro saas that provides API that calculates the Canada payroll deduction using the T4127 formula.

Is this something that anyone would pay for?

@Meekcanadian
Copy link

Meekcanadian commented Feb 8, 2024 via email

@vynci
Copy link

vynci commented Feb 8, 2024

Nice to hear from you @Meekcanadian, I've worked on a project recently that needed to calculate payroll deductions, it wasn't an easy problem to solve as I didn't find any existing API services for it. Every province has its specific formulas and constants, and on top of that, things could change twice a year, so the code needs to be changed as well.

I think creating a micro saas for this would be a good idea.

@Meekcanadian
Copy link

Meekcanadian commented Feb 8, 2024 via email

@vynci
Copy link

vynci commented Feb 8, 2024

Awesome, I will keep you posted @Meekcanadian. Thanks!

@Meekcanadian
Copy link

Meekcanadian commented Feb 8, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment