Bol retailer API - while loop vragen
Ik heb een platform waar bol verkopers via de bol retailer API: https://api.bol.com/retailer/public/Retailer-API/index.html
Een koppeling maken met mijn platform. Ik doe nu het volgende:
1. Tabel met bol accounts ( 10 stuks )
2. Via een cronjob door de bol accounts loopen en API calls maken om de orders op te halen.
Er zitten rate limits aan de API calls bijv 5 calls per minuut mag je maken.
Ik vind de code die ik nu heb niet stabiel genoeg en hoor graag hoe dit beter kan.
Zo zijn er klanten met echt veel orders waardoor die soms vastloopt lijkt het, is een cronjob met een while loop wel de beste manier, lijkt wel alsof die oneindig doorgaat maar niet van alle klanten de orders ophaalt.
Hoor het graag. Zit even niet op de pc dus heb geen voorbeeld code, update ik morgen even.
Mvg Furio
Ben benieuwd naar de code.
Je wilt toch eigenlijk niet dat een account dat 1 order per uur ontvangt, last heeft van traagheid die veroorzaakt wordt doordat je steeds voor 2 andere accounts 1000 per uur moet ophalen.
Zie hier de cronjob code die ervoor zorgt dat de orders vanuit bol in mijn database geschoten worden:
Code (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
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
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
include("/home/admin/domains/domain.com/public_html/includes/database.php");
include("/home/admin/domains/domain.com/public_html/includes/global-functions.php");
$database = new database();
// check of cron nog bezig is.
$q = 'SELECT cron_done FROM cron_status WHERE cron_systeem = "orders" ORDER BY id DESC LIMIT 1';
$result = $database->query($q);
while ($row = mysqli_fetch_assoc($result))
{
if ($row['cron_done'] == 1)
{
$q = 'INSERT INTO cron_status (tijd_begonnen, cron_systeem, cron_done) VALUES (NOW(), "orders" ,0)';
$database->query($q);
// je kan starten, vorige cron is done.
}
else
{
// CRON IS NOG NIET KLAAR!
die();
}
}
// Pak alle klanten waarbij bol gekoppeld is
$q = 'SELECT * FROM bol_accounts WHERE bol_token != "" AND status = 1';
$result = $database->query($q);
while ($rows = mysqli_fetch_assoc($result))
{
// check of sessie nog actief is, zo niet vraag nieuwe token op.
getCheckAccountNewBolToken($rows['klant_id'], $rows['id']);
$counterTimeout = 0;
$counter = 0;
$x = 1;
// pak tot 50 pagina's mee.
for ($x; $x <= 50; $x++)
{
$orderLink = "https://api.bol.com/retailer/shipments?fulfilment-method=FBR&page=".$x."";
$headers = ['Accept' => 'application/json'];
$ch = curl_init($orderLink);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET' );
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/vnd.retailer.v7+json',
'Authorization: Bearer ' . getAccountBolToken($rows['id'], $rows['klant_id']),
'Accept: application/vnd.retailer.v7+json',
));
// execute!
$response = curl_exec($ch);
$err = curl_error($ch);
// close the connection, release resources used
curl_close($ch);
$json = json_decode($response,true);
// check of rate limit is bereikt, 429 = rate limit bereikt.
if ($json['status'] == "429")
{
// limiet bereikt.
$counterTimeout++;
sleep(60); // 1 minuut rust dan kunnen we weer 7x loopen.
}
if ($response == "{}" || $response == "{ }" || $response == "")
{
// geen orders meer.
$paginageenOrders = $x;
$x = 51;
}
else
{
foreach($json as $key=>$val)
{
if(is_array($val))
{
foreach($val as $key=>$val)
{
if(is_array($val))
{
$sShipmentId = $val['shipmentId'];
$shipmentOrderId = $val['order']['orderId'];
$aantalOpgehaaldeorders++;
// check of order al is geimporteerd, zo niet importeer.
$qt = 'SELECT shipment_id FROM bol_orders WHERE shipment_id = "'.$sShipmentId.'" AND klant_id = "'.$rows['klant_id'].'" AND bol_account_id = "'.$rows['id'].'" ';
$resultt = $database->query($qt);
if (mysqli_num_rows($resultt) == 0)
{
// voer gegevens in want order bestaat nog niet.
$q = 'INSERT INTO bol_orders (klant_id, bol_account_id,shipment_id,shipment_order_id) VALUES ("'.$rows['klant_id'].'", "'.$rows['id'].'", "'.$sShipmentId.'", "'.$shipmentOrderId.'")';
$database->query($q);
}
$counter++;
}
}
}
else
{
}
}
}
// zendingen zijn opgehaald.
}
}
// update cron dat die klaar is.
$q = 'UPDATE cron_status SET cron_done = 1, tijd_klaar = NOW(), opgehaalde_orders = "'.$OpgehaaldeOrdersCronTotal.'" WHERE id = "'.getCronLatestId().'"';
$database->query($q);
?>
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
include("/home/admin/domains/domain.com/public_html/includes/database.php");
include("/home/admin/domains/domain.com/public_html/includes/global-functions.php");
$database = new database();
// check of cron nog bezig is.
$q = 'SELECT cron_done FROM cron_status WHERE cron_systeem = "orders" ORDER BY id DESC LIMIT 1';
$result = $database->query($q);
while ($row = mysqli_fetch_assoc($result))
{
if ($row['cron_done'] == 1)
{
$q = 'INSERT INTO cron_status (tijd_begonnen, cron_systeem, cron_done) VALUES (NOW(), "orders" ,0)';
$database->query($q);
// je kan starten, vorige cron is done.
}
else
{
// CRON IS NOG NIET KLAAR!
die();
}
}
// Pak alle klanten waarbij bol gekoppeld is
$q = 'SELECT * FROM bol_accounts WHERE bol_token != "" AND status = 1';
$result = $database->query($q);
while ($rows = mysqli_fetch_assoc($result))
{
// check of sessie nog actief is, zo niet vraag nieuwe token op.
getCheckAccountNewBolToken($rows['klant_id'], $rows['id']);
$counterTimeout = 0;
$counter = 0;
$x = 1;
// pak tot 50 pagina's mee.
for ($x; $x <= 50; $x++)
{
$orderLink = "https://api.bol.com/retailer/shipments?fulfilment-method=FBR&page=".$x."";
$headers = ['Accept' => 'application/json'];
$ch = curl_init($orderLink);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET' );
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/vnd.retailer.v7+json',
'Authorization: Bearer ' . getAccountBolToken($rows['id'], $rows['klant_id']),
'Accept: application/vnd.retailer.v7+json',
));
// execute!
$response = curl_exec($ch);
$err = curl_error($ch);
// close the connection, release resources used
curl_close($ch);
$json = json_decode($response,true);
// check of rate limit is bereikt, 429 = rate limit bereikt.
if ($json['status'] == "429")
{
// limiet bereikt.
$counterTimeout++;
sleep(60); // 1 minuut rust dan kunnen we weer 7x loopen.
}
if ($response == "{}" || $response == "{ }" || $response == "")
{
// geen orders meer.
$paginageenOrders = $x;
$x = 51;
}
else
{
foreach($json as $key=>$val)
{
if(is_array($val))
{
foreach($val as $key=>$val)
{
if(is_array($val))
{
$sShipmentId = $val['shipmentId'];
$shipmentOrderId = $val['order']['orderId'];
$aantalOpgehaaldeorders++;
// check of order al is geimporteerd, zo niet importeer.
$qt = 'SELECT shipment_id FROM bol_orders WHERE shipment_id = "'.$sShipmentId.'" AND klant_id = "'.$rows['klant_id'].'" AND bol_account_id = "'.$rows['id'].'" ';
$resultt = $database->query($qt);
if (mysqli_num_rows($resultt) == 0)
{
// voer gegevens in want order bestaat nog niet.
$q = 'INSERT INTO bol_orders (klant_id, bol_account_id,shipment_id,shipment_order_id) VALUES ("'.$rows['klant_id'].'", "'.$rows['id'].'", "'.$sShipmentId.'", "'.$shipmentOrderId.'")';
$database->query($q);
}
$counter++;
}
}
}
else
{
}
}
}
// zendingen zijn opgehaald.
}
}
// update cron dat die klaar is.
$q = 'UPDATE cron_status SET cron_done = 1, tijd_klaar = NOW(), opgehaalde_orders = "'.$OpgehaaldeOrdersCronTotal.'" WHERE id = "'.getCronLatestId().'"';
$database->query($q);
?>
Los van het probleem.
Een goede tip: Pas je cronjob commando aan dat je eerst naar de directorie van het script navigereert en dan met && je script met relatief pad aanroept. Dan hoef je geen hardcoded pad te gebruiken.
Gewijzigd op 07/12/2023 09:39:44 door - Ariën -
- Ariën - op 07/12/2023 09:38:32:
Wat Ivo zegt. Gewoon een cronjob per klant runnen.
Los van het probleem.
Een goede tip: Pas je cronjob commando aan dat je eerst naar de directorie van het script navigereert en dan met && je script met relatief pad aanroept. Dan hoef je geen hardcoded pad te gebruiken.
Los van het probleem.
Een goede tip: Pas je cronjob commando aan dat je eerst naar de directorie van het script navigereert en dan met && je script met relatief pad aanroept. Dan hoef je geen hardcoded pad te gebruiken.
Bedankt voor de tip! Hoe moet ik een cronjob per klant voor mij zien? Ik kan toch niet handmatig voor iedere nieuwe klant een cronjob aanmaken in directadmin?
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
// sort - Sorts the string in memory alphabetically.
// uniq - Removes any duplicate cron jobs from the string in memory.
// crontab - Writes the string in memory to the crontab file
shell_exec("(crontab -l ; echo '* * * * * python3 /usr/local/jobs/newjob.py') | sort | uniq | crontab");
?>
// sort - Sorts the string in memory alphabetically.
// uniq - Removes any duplicate cron jobs from the string in memory.
// crontab - Writes the string in memory to the crontab file
shell_exec("(crontab -l ; echo '* * * * * python3 /usr/local/jobs/newjob.py') | sort | uniq | crontab");
?>
Alleen de parameter (klant_id) moet ik nog mee kunnen geven en de volgende vragen die omhoog komen:
1. Kan je bij 1000 klanten wel 1000 cronjobs aanmaken welke continue runnen?
2. Wat als een klant zijn account opzegt, moet ik dan de cronjob stopzetten?
3. De Bol retailer API werkt hetzelfde bij het opaheln van producten, reviews, terugbetalingen etc, zal ik daar ook voor iedere klant een cronjob aanmaken?
Echt super bedankt voor het meedenken!!!!
Je zou deze cronjob kunnen draaien:
En voor klant2 kan je kiezen dat je die een uurtje later doet, afhankelijk hoe lang een cronjob duurt. Je wilt niet tegen de limieten van de Bol.com API aanlopen. Dus dat moet je even goed verspreid uitvoeren.
Bij het uitvoeren van een cronjob (gaat via de CLI) kan je controleren of $argv[1] (die bestaat dan gewoon) de klantnaam als argument bevat. Dan kan je kijken of die bestaat in je database waar je klanten in staan. Bestaat de klant niet (meer) dan kan je de cronjob via de DirectAdmin API verwijderen, of een techneut op de IT-afdeling een seintje geven om de cronjob te verwijderen.
Ik zou alle processen die moeten plaatsvinden bij de Retailer API in één klant cronjob uitvoeren. of zijn er taken die licht zijn, eventueel vaker worden uitgevoerd en gebundeld kunnen worden? Dan kan dat in een aparte globale cronjob.
Documenteer wel goed welke processen wanneer moeten plaatsvinden, en log dit ook allemaal!
Gewijzigd op 07/12/2023 10:55:33 door - Ariën -
je zet nu een lock in de database om te controleren of je job mag runnen.
Ik zou gaan voor een lock op de bol_accounts tabel:
Je cron start je gewoon elke minuut. (of 5 of 10, wat jij leuk vindt).
Die kijkt naar de tabel bol_accounts en select daaruit 1.
Deze ene krijgt een lock en een tijdstip van starten daarbij.
Daarmee doe je je ding.
1 minuut later start het script weer en uit de tabel bol_accounts select je een die geen lock heeft en het langst geleden gestart is geweest.
Die krijgt ook een lock.
Eventueel doe je nog een extra check om te kijken of er niet al 5 jobs draaien.
To be continued
Het lijkt erop dat de Bol API mijn server een x aantal aanvragen geeft per aanvraag aangezien ik heel erg vaak een curl error 7 ontvang, (geen connectie), ik krijg dan niets terug en als ik een paar keer refresh reageert de api soms wel.
Via postman krijg ik elke aanvraag antwoord.
Via een andere server van mij ook.
Moet dus bij mijn server liggen, kan het zijn dat bol een limit kan zetten per ipadres buiten de standaard rate limits, zo ja, kan ik nooit betrouwbaar de api gebruiken...
Iemand een idee wat te doen buiten bol contacteren (hopeloze zaak)?
Mijn advies: Vraag Bol.com
Ik heb nu de oplossing van Ivo gebouwd als het goed is?
Verder heb ik extra checks ingebouwd om te zorgen dat ik binnen de rate limits blijf van de API alleen weet iemand hoe je vanuit een header array een waarde kan selecteren, zie regel " $iRateLimitRemaining = ''; // Hier moet de waarde komen vanuit de array met key: x-ratelimit-remaining", ben daar wat slecht in.
Dan het belangrijkste, hoe schaalbaar is deze gehele oplossing, zo lijkt het mij bij deze oplossing dat ik bij 1000 klanten alsnog 1000 minuten moet wachten alvorens iedere klant zijn laatste bestellingen binnen heeft.
Code (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
222
223
224
225
226
227
228
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
222
223
224
225
226
227
228
<?php
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL);
$database = new database();
// rate limit 25 per minuut.
// Als klant net nieuw is moet die de eerste zijn waarvan we de orders ophalen.
// Pak 1 klant waarbij bol gekoppeld is EN ER GEEN LOCK OP ZIT, order bij nieuwste klant en eerst gerunde cron.
$q = 'SELECT * FROM bol_accounts WHERE bol_token != "" AND status = 1 AND cron_orders_lock = 0 ORDER BY cron_orders_start ASC, ID DESC LIMIT 1 ';
$result = $database->query($q);
while ($rows = mysqli_fetch_assoc($result))
{
// lock deze bol account zodat die niet weer gestart gaat worden.
$q = 'UPDATE bol_accounts SET cron_orders_lock = 1 WHERE id = "'.$rows['id'].'"';
$database->query($q);
// log de start tijd.
$q = 'UPDATE bol_accounts SET cron_orders_start = NOW() WHERE id = "'.$rows['id'].'"';
$database->query($q);
// check of sessie nog actief is, zo niet vraag nieuwe token op.
getCheckAccountNewBolToken($rows['klant_id'], $rows['id']);
$counter = 0;
$x = 1;
// pak tot 50 pagina's mee = 50x50. 2500 orders.
for ($x; $x <= 50; $x++)
{
$lastStatusCode = '';
$iRateLimitRemaining = ''; // 24
$iRateLimitReset = ''; //in seconden
if ($lastStatusCode != "200")
{
die("Geen goede response meer vanuit de bol api".$lastStatusCode);
}
if ($iRateLimitRemaining < 2)
{
sleep($iRateLimitReset); // Sleep tot de rate limit reset is.
}
$orderLink = "https://api.bol.com/retailer/shipments?fulfilment-method=FBR&page=".$x.""; //get all orders tot response leeg is wat betekent dat er geen orders meer zijn
$headers = ['Accept' => 'application/json'];
$ch = curl_init($orderLink);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true); // toegevoegd om headers te krijgen
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET' );
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/vnd.retailer.v10+json',
'Authorization: Bearer ' . getAccountBolToken($rows['id'], $rows['klant_id']),
'Accept: application/vnd.retailer.v10+json',
));
// execute!
$response = curl_exec($ch);
$err = curl_error($ch);
$sResponseCode = curl_getinfo( $ch , CURLINFO_RESPONSE_CODE );
$lastStatusCode = $sResponseCode;
// Return headers seperatly from the Response Body
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $header_size);
$body = substr($response, $header_size);
$headers = explode("\r\n", $headers); // The seperator used in the Response Header is CRLF (Aka. \r\n)
$headers = array_filter($headers);
foreach ($headers as $value)
{
//echo $value."<br/>";
$iRateLimitRemaining = ''; // Hier moet de waarde komen vanuit de array met key: x-ratelimit-remaining
$iRateLimitReset = ''; // Hier moet de waarde komen vanuit de array met key: x-ratelimit-reset
}
// close the connection, release resources used
curl_close($ch);
$json = json_decode($body,true);
// teveel aanvragen melding check
if ($json['status'] == "429")
{
// limiet bereikt.
echo "limiet bereikt 429";
die("limiet bereikt van 429"); // Betekent dat we iets niet goed hebben gedaan bij de rate limits controle.
}
if ($response == "{}" || $response == "{ }" || $response == "")
{
echo 'Bol account ID:'.$rows['id']." heeft geen orders meer vanaf pagina:".$x;
$paginageenOrders = $x;
$x = 51;
//die(); moet ik hier die() doen of stopt die vanzelf omdat de waarde 51 is?
// geen orders meer.
}
else
{
foreach($json as $key=>$val)
{
$OpgehaaldeOrders += count($json['shipments']);
$OpgehaaldeOrdersCronTotal += count($json['shipments']);
if(is_array($val))
{
foreach($val as $key=>$val)
{
if(is_array($val))
{
$sShipmentId = $val['shipmentId'];
$shipmentOrderId = $val['order']['orderId'];
$aantalOpgehaaldeorders++;
// check of order al is geimporteerd, zo niet importeer.
$qt = 'SELECT shipment_id FROM bol_orders WHERE shipment_id = "'.$sShipmentId.'" AND klant_id = "'.$rows['klant_id'].'" AND bol_account_id = "'.$rows['id'].'" ';
$resultt = $database->query($qt);
if (mysqli_num_rows($resultt) == 0)
{
// voer gegevens in
$q = 'INSERT INTO bol_orders (klant_id, bol_account_id,shipment_id,shipment_order_id, created_at) VALUES ("'.$rows['klant_id'].'", "'.$rows['id'].'", "'.$sShipmentId.'", "'.$shipmentOrderId.'", NOW())';
echo $q.'<br/>';
$database->query($q);
}
$counter++;
}
}
}
else
{
}
}
}
echo $rows['id']." gelooped"."<br/>";
}
// log de eind tijd.
$q = 'UPDATE bol_accounts SET cron_orders_eind = NOW() WHERE id = "'.$rows['id'].'"';
$database->query($q);
// release de lock zodat die weer op nieuw kan.
$q = 'UPDATE bol_accounts SET cron_orders_lock = 0 WHERE id = "'.$rows['id'].'"';
$database->query($q);
}
?>
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
error_reporting(E_ALL);
$database = new database();
// rate limit 25 per minuut.
// Als klant net nieuw is moet die de eerste zijn waarvan we de orders ophalen.
// Pak 1 klant waarbij bol gekoppeld is EN ER GEEN LOCK OP ZIT, order bij nieuwste klant en eerst gerunde cron.
$q = 'SELECT * FROM bol_accounts WHERE bol_token != "" AND status = 1 AND cron_orders_lock = 0 ORDER BY cron_orders_start ASC, ID DESC LIMIT 1 ';
$result = $database->query($q);
while ($rows = mysqli_fetch_assoc($result))
{
// lock deze bol account zodat die niet weer gestart gaat worden.
$q = 'UPDATE bol_accounts SET cron_orders_lock = 1 WHERE id = "'.$rows['id'].'"';
$database->query($q);
// log de start tijd.
$q = 'UPDATE bol_accounts SET cron_orders_start = NOW() WHERE id = "'.$rows['id'].'"';
$database->query($q);
// check of sessie nog actief is, zo niet vraag nieuwe token op.
getCheckAccountNewBolToken($rows['klant_id'], $rows['id']);
$counter = 0;
$x = 1;
// pak tot 50 pagina's mee = 50x50. 2500 orders.
for ($x; $x <= 50; $x++)
{
$lastStatusCode = '';
$iRateLimitRemaining = ''; // 24
$iRateLimitReset = ''; //in seconden
if ($lastStatusCode != "200")
{
die("Geen goede response meer vanuit de bol api".$lastStatusCode);
}
if ($iRateLimitRemaining < 2)
{
sleep($iRateLimitReset); // Sleep tot de rate limit reset is.
}
$orderLink = "https://api.bol.com/retailer/shipments?fulfilment-method=FBR&page=".$x.""; //get all orders tot response leeg is wat betekent dat er geen orders meer zijn
$headers = ['Accept' => 'application/json'];
$ch = curl_init($orderLink);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true); // toegevoegd om headers te krijgen
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET' );
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/vnd.retailer.v10+json',
'Authorization: Bearer ' . getAccountBolToken($rows['id'], $rows['klant_id']),
'Accept: application/vnd.retailer.v10+json',
));
// execute!
$response = curl_exec($ch);
$err = curl_error($ch);
$sResponseCode = curl_getinfo( $ch , CURLINFO_RESPONSE_CODE );
$lastStatusCode = $sResponseCode;
// Return headers seperatly from the Response Body
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $header_size);
$body = substr($response, $header_size);
$headers = explode("\r\n", $headers); // The seperator used in the Response Header is CRLF (Aka. \r\n)
$headers = array_filter($headers);
foreach ($headers as $value)
{
//echo $value."<br/>";
$iRateLimitRemaining = ''; // Hier moet de waarde komen vanuit de array met key: x-ratelimit-remaining
$iRateLimitReset = ''; // Hier moet de waarde komen vanuit de array met key: x-ratelimit-reset
}
// close the connection, release resources used
curl_close($ch);
$json = json_decode($body,true);
// teveel aanvragen melding check
if ($json['status'] == "429")
{
// limiet bereikt.
echo "limiet bereikt 429";
die("limiet bereikt van 429"); // Betekent dat we iets niet goed hebben gedaan bij de rate limits controle.
}
if ($response == "{}" || $response == "{ }" || $response == "")
{
echo 'Bol account ID:'.$rows['id']." heeft geen orders meer vanaf pagina:".$x;
$paginageenOrders = $x;
$x = 51;
//die(); moet ik hier die() doen of stopt die vanzelf omdat de waarde 51 is?
// geen orders meer.
}
else
{
foreach($json as $key=>$val)
{
$OpgehaaldeOrders += count($json['shipments']);
$OpgehaaldeOrdersCronTotal += count($json['shipments']);
if(is_array($val))
{
foreach($val as $key=>$val)
{
if(is_array($val))
{
$sShipmentId = $val['shipmentId'];
$shipmentOrderId = $val['order']['orderId'];
$aantalOpgehaaldeorders++;
// check of order al is geimporteerd, zo niet importeer.
$qt = 'SELECT shipment_id FROM bol_orders WHERE shipment_id = "'.$sShipmentId.'" AND klant_id = "'.$rows['klant_id'].'" AND bol_account_id = "'.$rows['id'].'" ';
$resultt = $database->query($qt);
if (mysqli_num_rows($resultt) == 0)
{
// voer gegevens in
$q = 'INSERT INTO bol_orders (klant_id, bol_account_id,shipment_id,shipment_order_id, created_at) VALUES ("'.$rows['klant_id'].'", "'.$rows['id'].'", "'.$sShipmentId.'", "'.$shipmentOrderId.'", NOW())';
echo $q.'<br/>';
$database->query($q);
}
$counter++;
}
}
}
else
{
}
}
}
echo $rows['id']." gelooped"."<br/>";
}
// log de eind tijd.
$q = 'UPDATE bol_accounts SET cron_orders_eind = NOW() WHERE id = "'.$rows['id'].'"';
$database->query($q);
// release de lock zodat die weer op nieuw kan.
$q = 'UPDATE bol_accounts SET cron_orders_lock = 0 WHERE id = "'.$rows['id'].'"';
$database->query($q);
}
?>
Hier verandert de inhoud van $headers ineens van een string naar een array.
Voor de duidelijkheid zou ik dat niet doen, maar daar bijvoorbeeld van maken:
nb: het kan ook goed zijn dan de new line alleen maar \n is!
Regel 92 doet mi. niet heel veel nuttigs.
Maar dan is wel de plek om eens te kijken wat er in je array zit:
Daaropvolgend probeer je iets met een foreach lus door het array te gaan.
Dat is niet de handigste methode:
Zie wat er uit de var_dump() komt en het je dan
$iRateLimitRemaining = $headerArray[....]
kunt gebruiken.
Aangezien deze header mogelijk ontbreekt zou je ook kunnen doen
(en wat op .... moet komen, mag je zelf even uit var_dump zoeken.
Toevoeging op 13/12/2023 10:52:31:
enne:
429 is niet de grootte van de limit, maar een status-code die aangeeft "er is een request limiet bereikt".
Net als 404 staat voor Not Found of 401 voor "geen toegang"
en 418 voor "ik ben een theepot"
https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_client_errors
Toevoeging op 13/12/2023 13:19:36:
update query's kunnen trouwens ook in 1x meerdere velden aanpassen:
Ik heb het nu volledig werkend en het is een stuk meer bulletproof met de eerste versie maar zoals gezegd wil ik het graag gelijk future proof hebben daar ik 30% van me klanten ben verloren door onzorgvuldige code met teveel bugs
Daarom mijn zorgen of de oplossing met een lock op de bol_accounts tabel future proof is.
1. Cronjob runt deze code elke minuut en pakt dus steeds een bol account waar geen lock op zit en welke het laatst is gerunt.
2. Naar mijn mening duurt deze manier alsnog 1000minuten bij 1000 klanten.
3. Wat gebeurd er in een cronjob welke elke minuut runt als er een klant is welke door de rate limit 2/3x x aantal seconden moet “sleepen” wachten? Maakt de cron de huidige job af of start die gewoon opnieuw de code na 1minuut waardoor klanten dus niet volledige orders te zien krijgen toch?
4. Dit is 1 van de vele api points, zo heb ik ook nog moelijkere zoals “offers” producten welke je in 3 stappen moet doen bij de bol API namelijk:
4.1 vraag een excell export aan.
4.2 je krijgt dan een status ID welke je zelf moet checken als een soort webhook of deze de status “success” heeft.
4.3 als deze succes heeft krijg je een excell bestand met de producten van de retailer.
Ik wilde dezelfde oplossing toepassen maar misschien weet er iemand iets beters? Het doel is dat een klant zsm zijn bestaande en daarna nieuw toegevoegde producten te zien krijgt.
Sorry voor de vragen maar er zitten hier programmeurs met jaren meer ervaring als ik dus advies is altijd welkom.
Ik denk dat je dan wel een speciaal contract met Bol.com hebt die alles naar jou zou pushen zodat jij je geen druk hoeft te maken om limitrates. ;-)
Voor processen waarbij het eventjes duurt voordat de data compleet is (als er van alles bij verzameld moet worden), zou ik de data nog even buiten beeld houden totdat alles compleet is. Je kan een flag plaatsen met 'completed'.
Gewijzigd op 14/12/2023 00:07:43 door - Ariën -