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.

Revisions

  1. reinvented revised this gist Jun 14, 2018. 1 changed file with 140 additions and 84 deletions.
    224 changes: 140 additions & 84 deletions pdoc.php
    Original file line number Diff line number Diff line change
    @@ -1,99 +1,144 @@
    <?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);
    /**
    * get-pdoc.php - Scrape Canada Revenue Agency payroll deductions values
    *
    * This script takes an hourly amount, a number of hours, and a year,
    * month and day of a pay period ending, and passes these to the
    * Canada Revenue Agency Payroll Deductions Online Calculator
    * (https://www.canada.ca/en/revenue-agency/services/e-services/e-services-businesses/payroll-deductions-online-calculator.html),
    * returning the provincial tax, federal tax, CPP and EI amounts.
    *
    * This program is free software; you can redistribute it and/or modify
    * it under the terms of the GNU General Public License as published by
    * the Free Software Foundation; either version 2 of the License, or (at
    * your option) any later version.
    * This program is distributed in the hope that it will be useful, but
    * WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    * General Public License for more details.
    * You should have received a copy of the GNU General Public License
    * along with this program; if not, write to the Free Software
    * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    * USA
    *
    * @version 0.2, June 14, 2018
    * @author Peter Rukavina <peter@rukavina.net>
    * @copyright Copyright &copy; 2018, Reinvented Inc.
    * @license http://www.fsf.org/licensing/licenses/gpl.txt GNU Public License
    */

    // Get from http://simplehtmldom.sourceforge.net/
    include('simple_html_dom.php');

    $retval = array();
    $retval['status'] = 'success';

    $required = array('hours', 'hourly', 'year', 'month', 'day');
    foreach($required as $key => $value) {
    if (!array_key_exists($value, $_GET)) {
    $retval['status'] = 'error';
    $retval['errormessage'] = "Missing '" . $value . "' parameter.";
    }
    }

    if (array_key_exists('i', $options)) {
    $param['income'] = $options['i'];
    }
    if ($retval['status'] != 'error') {

    if (array_key_exists('v', $options)) {
    $param['vacationPay'] = $options['v'];
    }
    $param = array();

    $requiredParams = array('year' => '', 'month' => '', 'day' => '', 'income' => '', 'vacationPay' => '');
    $missingParams = array_diff_key($requiredParams, $param);
    $param['income'] = ($_GET['hourly'] * $_GET['hours']);
    $param['vacationPay'] = round($param['income'] * 0.04, 2);
    $param['year'] = $_GET['year'];
    $param['month'] = $_GET['month'];
    $param['day'] = $_GET['day'];

    if (count($missingParams)) {
    die("Usage: get-pdoc.php -i [income] -v [vacation pay] -d [date]\n\n");
    }
    $param['month'] = str_pad($param['month'], 2, '0', STR_PAD_LEFT);
    $param['day'] = str_pad($param['day'], 2, '0', STR_PAD_LEFT);

    $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]]);
    $data = array(
    "step0" => array(
    "calculationType" => "SALARY", // Salary
    "action:welcome_NextButton" => "Next",
    "struts.token.name" => "166PXW9HKHFUX4B37TTDTLBYFEK2SGPC",
    ),
    "step1" => array(
    "employeeName" => "The Employee",
    "employerName" => "The Employer",
    "jurisdiction" => "PRINCE_EDWARD_ISLAND", // Prince Edward Island
    "payPeriodFrequency" => "WEEKLY_52PP", // Weekly
    "datePaidYear" => $param['year'],
    "datePaidMonth" => $param['month'],
    "datePaidDay" => $param['day'],
    "action:payrollDeductionsStep1_NextButton" => "Next"
    ),
    "step2" => array(
    "incomeAmount" => $param['income'],
    "vacationPay" => $param['vacationPay'],
    "salaryType" => "NO_BONUS_PAY_NO_RETROACTIVE_PAY",
    "clergyType" => "NOT_APPLICABLE",
    "action:payrollDeductionsStep2a_NextButton" => "Next"
    ),
    "step3" => array(
    "federalClaimCode" => "CLAIM_CODE_1",
    "provinceTerritoryClaimCode" => "CLAIM_CODE_1",
    "requestedAdditionalTaxDeductions" => "0.00",
    "pensionableEarningsYearToDate" => "0",
    "cppOrQppContributionsDeductedYearToDate" => "0",
    "cppQppType" => "CPP_QPP_YEAR_TO_DATE",
    "insurableEarningsYearToDate" => "0",
    "employmentInsuranceType" => "EI_YEAR_TO_DATE",
    "employmentInsuranceDeductedYearToDate" => "0",
    "reducedEIRate" => "0",
    "employerEmploymentInsurancePremiumRate" => 1.4,
    "action:payrollDeductionsStep3_CalculateButton" => "Calculate"
    ),
    );

    $triggers = array(
    "federalTax" => array("Federal tax deduction", 3),
    "provincialTax" => array("Provincial tax deduction", 4),
    "CPP" => array("CPP deductions", 4),
    "EI" => array("EI deductions", 4),
    );

    $result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/prot/welcome.action", array('post' => false));

    $hidden = getHiddenFormValueFromHTML($result);
    $data['step0'] = array_merge($data['step0'], $hidden);

    $result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/prot/welcome.action", array('hidden' => $hidden, 'refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/prot/welcome.action', 'post' => http_build_query($data['step0'], '', '&')));

    $hidden = getHiddenFormValueFromHTML($result);
    $data['step1'] = array_merge($data['step1'], $hidden);

    $result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/prot/payrollDeductionsStep1.action", array('refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/prot/welcome.action', 'post' => http_build_query($data['step1'], '', '&')));

    $hidden = getHiddenFormValueFromHTML($result);
    $data['step2'] = array_merge($data['step2'], $hidden);

    $result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/prot/payrollDeductionsStep2a.action", array('refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/prot/payrollDeductionsStep1.action', 'post' => http_build_query($data['step2'], '', '&')));

    $hidden = getHiddenFormValueFromHTML($result);
    $data['step3'] = array_merge($data['step3'], $hidden);

    $result = fetch("https://apps.cra-arc.gc.ca/ebci/rhpd/prot/payrollDeductionsStep3.action", array('refer' => 'https://apps.cra-arc.gc.ca/ebci/rhpd/prot/payrollDeductionsStep2a.action', '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]]);
    }
    }
    }
    $retval['values'] = $values;
    }

    print_r($values);
    print json_encode($retval);

    function fetch( $url, $z=null ) {
    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';
    @@ -114,5 +159,16 @@ function fetch( $url, $z=null ) {

    $result = curl_exec( $ch );
    curl_close( $ch );

    return $result;
    }

    function getHiddenFormValueFromHTML($html) {
    $html = str_get_html($html);
    $nodes = $html->find("input[type=hidden]");
    $hidden = array();
    foreach ($nodes as $node) {
    $hidden[$node->attr['name']] = $node->attr['value'];
    }
    return $hidden;
    }
  2. reinvented created this gist Feb 3, 2017.
    118 changes: 118 additions & 0 deletions pdoc.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,118 @@
    <?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;
    }