-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxero-privapp-testendpoints.php
221 lines (195 loc) · 6.77 KB
/
xero-privapp-testendpoints.php
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<?php
# xero-privapp-testendpoints.php
# nearly minimal xero private application
# jcl/jclxx/2018-10-24
#################################################################
# HELLO WORLD FOR XERO ACCOUNTING ("PRIVATE" APP)
# see http://developer.xero.com
#
# simple hello-world program to test private app authenticaton
# from php using xero-php library. it tests lots of endpoints
# and prints just a few useful fields from each one.
#
# this is for "private" app, not "public" or "partner".
#
# make xero-privapp-helloworld.php work before using this one.
#
# requires php7.2 php7.2-curl php7.2-xml composer unzip
# then "composer require calcinai/xero-php"
# also SECRETSDIR/consumerkey (from xero app page)
# also SECRETSDIR/privatekey.pem (see accompanying createprivapp.sh)
#################################################################
#################################################################
# PREREQUISITES
#################################################################
# check composer parts seem to be in place
# it gives an autoloader to load classes on demand
#
if (!file_exists('composer.json') || !file_exists('vendor/autoload.php')) {
printf("ERROR: missing composer parts\n");
printf(" did you run \"composer require calcinai/xero-php\" ?\n");
exit (1);
}
include 'vendor/autoload.php';
use XeroPHP\Application\PrivateApplication;
#################################################################
# CONFIG
#################################################################
# we expect our secrets in here
#
define('SECRETSDIR', './secretprivapp');
define('CONSUMERKEYFILE', SECRETSDIR . '/consumerkey');
define('PRIVATEKEYFILE', SECRETSDIR . '/privatekey.pem');
define('PUBLICKEYFILE', SECRETSDIR . '/publickey.cer');
define('NAGFILE', SECRETSDIR . '/NAGABOUTKEY');
# minimal config for private app
# callback and consumer_secret required but value irrelevant
# do not use "file://" construction for consumer_key
#
$config = [
'oauth' => [
'callback' => "not used in private apps",
'consumer_key' =>
trim(@file_get_contents(CONSUMERKEYFILE)),
'consumer_secret' => "not used in private apps",
'rsa_private_key' => "file://" . PRIVATEKEYFILE,
],
];
# check we have a consumer key
#
if (!$config['oauth']['consumer_key']) {
printf("ERROR: %s is missing or empty\n", CONSUMERKEYFILE);
printf(" did you run \"sh createprivapp.sh\" ?\n");
exit (1);
}
# check it's not the dummy from the create script
#
if (preg_match("/DUMMY/", $config['oauth']['consumer_key'])) {
printf("WARNING: dummy consumer key\n");
printf(" expect \"Consumer key was not recognised\" error from xero\n");
printf(" fix by copying consumer key from xero app page to %s\n",
CONSUMERKEYFILE);
}
# check we have keys
#
if (!@file_get_contents(PRIVATEKEYFILE)) {
printf("ERROR: %s is missing or empty\n", PRIVATEKEYFILE);
printf(" did you run \"sh createprivapp.sh\" ?\n");
exit (1);
}
if (!@file_get_contents(PUBLICKEYFILE)) {
printf("ERROR: %s is missing or empty\n", PUBLICKEYFILE);
printf(" did you run \"sh createprivapp.sh\" ?\n");
exit (1);
}
# nag about uploading the public key if needed
#
if (file_exists(NAGFILE)) {
printf("WARNING: %s exists\n", NAGFILE);
printf(" expect \"Failed to validate signature\" from xero\n");
printf(" fix by copying %s to xero app page\n", PUBLICKEYFILE);
printf(" delete %s to remove this warning\n", NAGFILE);
}
#################################################################
# UTILITY
#################################################################
# to show token summaries
#
function offuscare($s)
{
return (substr($s, 0, 2) . "..." . substr($s, -2, 2));
}
#################################################################
# MAIN
#################################################################
# say what we're doing
#
printf("connecting to xero private app with consumer key %s\n",
offuscare($config['oauth']['consumer_key']));
printf("public key certificate fingerprint %s\n",
openssl_x509_fingerprint(file_get_contents(PUBLICKEYFILE)));
# create the structures
#
$xero = new PrivateApplication($config);
# list of app the api calls we are going to make
#
# all the endpoints we could find, and a few fields to print for each
# (or false to skip and true for print_r)
#
# note they are all plural names in xero api documentation
# but singular in the xero-php implementation
#
# see https://developer.xero.com/documentation/api
#
$thingnames = [
'Accounting\\Attachment' => false,
'Accounting\\Account' => ['Code', 'Name', 'Class'],
'Accounting\\BankStatement' => false,
'Accounting\\BankTransaction' => ['Type', 'CurrencyCode', 'Total'],
'Accounting\\BankTransfer' => true,
'Accounting\\BrandingTheme' => ['Name'],
'Accounting\\Contact' => ['Name', 'EmailAddress'],
'Accounting\\ContactGroup' => ['Name'],
'Accounting\\CreditNote' => ['Type', 'CurrencyCode', 'Total'],
'Accounting\\Currency' => ['Code', 'Description'],
'Accounting\\Employee' => ['FirstName', 'Lastname', 'Status'],
'Accounting\\ExpenseClaims (Deprecated)' => false,
'Accounting\\History' => false,
'Accounting\\Invoice' => ['InvoiceNumber', 'CurrencyCode', 'Total'],
'Accounting\\InvoiceReminder' => false,
'Accounting\\Item' => ['Code', 'Name', 'QuantityOnHand'],
'Accounting\\Journal' => ['JournalNumber'],
'Accounting\\LinkedTransaction' => true,
'Accounting\\ManualJournal' => ['Narration', 'Status'],
'Accounting\\Organisation' => ['Name', 'TaxNumber'],
'Accounting\\Overpayment' => true,
'Accounting\\PaymentServices' => false,
'Accounting\\Payment' => ['Amount', 'Reference', 'Status'],
'Accounting\\Prepayment' => true,
'Accounting\\PurchaseOrder' =>
['PurchaseOrderNumber', 'CurrencyCode', 'Total'],
'Accounting\\Quote' => false,
'Accounting\\Receipts (Deprecated)' => false,
'Accounting\\RepeatingInvoice' => ['Type', 'CurrencyCode', 'Total'],
'Accounting\\Report' => false,
'Accounting\\TaxRate' => ['Name', 'Status', 'EffectiveRate'],
'Accounting\\TrackingCategory' => ['Name', 'Status'],
'Accounting\\User' => ['FirstName', 'OrganisationRole'],
];
# now make all the api calls
#
$ii = 0;
foreach ($thingnames as $thingname => $fields) {
if ($fields === false) {
# deprecated or unknown endpoints
continue;
}
printf("== %d '%s' ==\n", $ii + 1, $thingname);
try {
$things = $xero->load($thingname)->execute();
} catch (Exception $e) {
printf("XERO ERROR %s: %s\n", $e->getCode(), $e->getMessage());
exit (1);
}
if (file_exists(NAGFILE)) {
unlink(NAGFILE);
printf("PS: deleted %s after successful call\n",
NAGFILE);
}
foreach ($things as $i => $thing) {
if ($fields === true) {
# don't know how to print this
print_r($thing);
continue;
}
printf(" %d.", $i + 1);
foreach ($fields as $field) {
printf(" %s=\"%s\"", $field, $thing->$field);
}
printf("\n");
}
++$ii;
}
printf("happy ending\n");
exit (0);
# end