We’ve recently started using Paymo to track our time and send invoices. So far I’ve been fairly impressed, it seems to do a good job.
We charge some of our customers a set amount per month that includes up to _x _hours of work during the month. It would be convenient for them to have a way to check to see how much time we’ve spent during the month (so they can keep track of how much time they have “left” for the month). Now that our time tracking is done in the cloud, I realized it would be possible to create a page that they could view this information on.
To keep things simple, I will just send our customers a link to view the monthly time for their project. I was a little worried about security though - the script receives the project ID number from the querystring. To keep someone from guessing the project ID for another customer’s project, I added a SHA1 hash onto the querystring. When I send a link out to a customer, I generate a SHA1 hash of the project ID concatenated with a secret key. The script then concatenates the project ID that its received with the secret key, and checks that with the hash that is sent to it through the querystring. The actual link a customer would receive looks kind of like this: http://www.example.com/paymo-time.php?pid=12345&hashsig=aBigLongSHA1Hash
The trickiest part was probably getting the XPath parts right. The Paymo API sends XML data back after you make the request, so I use XPath (through PHP’s SimpleXML) to pull out the relevant parts. Basically, this script:
- Verifies that the hash is valid
- Authenticates to Paymo
- Pulls the list of billable tasks for the given project
- Pulls the amount of time spent on each of those tasks in the current calendar month
- Adds the time together and displays the total for the whole project
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
<?php
$project_id = $_GET['pid'];
$hashsig = $_GET['hashsig'];
$salt = "RandomStringOfCharacters";
if (sha1($salt . $project_id) != $hashsig){
die("Invalid Authentication Token");
}
$api_key = "--MyPaymoAPIKey--";
$api_username = "--MyPaymoUsername--";
$api_password = "--MyPaymoPassword--";
$auth_token;
$start = date("Y-m-d H:i:s", strtotime(date('m').'/01/'.date('Y').' 00:00:00'));
$end = date("Y-m-d H:i:s", strtotime('-1 second',strtotime('+1 month',strtotime(date('m').'/01/'.date('Y').' 00:00:00'))));
$auth_token = paymoAuth($api_key,$api_username,$api_password);
$a1 = array(
'api_key' => $api_key,
'auth_token' => $auth_token,
'include_task_lists' => 1,
'include_tasks' => 1);
$tasklist = paymoAPI("paymo.projects.getList", $a1);
$project_name = $tasklist->xpath("/response/projects/project[@id=" . $project_id . "]/@name");
$project_name = $project_name[0];
$tasks = $tasklist->xpath("/response/projects/project[@id=" . $project_id . "]/task_lists/task_list/tasks/task[@billable="1"]/@id");
$time = 0;
foreach ($tasks as $task)
{
$a2 = array(
'api_key' => $api_key,
'auth_token' => $auth_token,
'task_id' => $task[0],
'start' => $start,
'end' => $end);
$taskinfo = paymoAPI("paymo.entries.getTrackedTimeByTask", $a2);
$tasktime = $taskinfo->xpath("/response/time/text()");
$tasktime = $tasktime[0];
$time += $tasktime;
}
print "<h1>Monthly Time for " . $project_name . "</h1><br/>";
print "<b>" . date("F Y") . ": </b>";
$time = mktime(0, 0, $time);
print date("H:i", $time) . " (HH:MM)";
function paymoAuth($api_key, $api_username, $api_password)
{
$args = array ( 'api_key' => $api_key, 'username' => $api_username, 'password' => $api_password );
$auth_token = paymoAPI("paymo.auth.login", $args)->xpath('/response/token/text()');
return $auth_token[0];
}
function paymoAPI($method, $args)
{
$base = "[https://api.paymo.biz/service/"](https://api.paymo.biz/service/") . $method . "?";
$qs = "";
foreach ($args as $key => $value){
$qs .= "$key=" . urlencode($value) . "&";
}
$url = $base . $qs;
$result = file_get_contents($url);
$xml_result = new SimpleXMLElement($result);
return $xml_result;
}
?>
|