File inc/admin.inc.php changed (mode: 100644) (index b098f7c..1f35723) |
... |
... |
function rg_admin_settings($db, &$rg, $paras) |
1272 |
1272 |
return $ret; |
return $ret; |
1273 |
1273 |
} |
} |
1274 |
1274 |
|
|
|
1275 |
|
/* |
|
1276 |
|
* Admin ->Settings -> Payments -> squareup |
|
1277 |
|
*/ |
|
1278 |
|
function rg_admin_pay_squareup_high_level($db, $rg) |
|
1279 |
|
{ |
|
1280 |
|
rg_log_enter('rg_admin_pay_squareup_high_level'); |
|
1281 |
|
|
|
1282 |
|
$ret = ''; |
|
1283 |
|
$errmsg = array(); |
|
1284 |
|
$hints = array(); |
|
1285 |
|
while ($rg['doit'] == 1) { |
|
1286 |
|
if (!rg_valid_referer()) { |
|
1287 |
|
$errmsg[] = 'invalid referer; try again'; |
|
1288 |
|
break; |
|
1289 |
|
} |
|
1290 |
|
|
|
1291 |
|
if (!rg_token_valid($db, $rg, 'admin_pay_squareup_high_level', FALSE)) { |
|
1292 |
|
$errmsg[] = 'invalid token; try again'; |
|
1293 |
|
break; |
|
1294 |
|
} |
|
1295 |
|
|
|
1296 |
|
$bearer = rg_var_str('bearer'); |
|
1297 |
|
$location_id = rg_var_str('location_id'); |
|
1298 |
|
|
|
1299 |
|
$r = rg_state_set($db, 'pay-squareup-bearer', $bearer); |
|
1300 |
|
if ($r === FALSE) { |
|
1301 |
|
$errmsg[] = 'cannot set state; try again'; |
|
1302 |
|
break; |
|
1303 |
|
} |
|
1304 |
|
|
|
1305 |
|
$r = rg_state_set($db, 'pay-squareup-location_id', $location_id); |
|
1306 |
|
if ($r === FALSE) { |
|
1307 |
|
$errmsg[] = 'cannot set state; try again'; |
|
1308 |
|
break; |
|
1309 |
|
} |
|
1310 |
|
|
|
1311 |
|
$rg['pay-squareup-bearer'] = $bearer; |
|
1312 |
|
$rg['pay-squareup-location_id'] = $location_id; |
|
1313 |
|
|
|
1314 |
|
$ret .= rg_template('admin/pay/ok.html', |
|
1315 |
|
$rg, TRUE /*xss*/); |
|
1316 |
|
break; |
|
1317 |
|
} |
|
1318 |
|
|
|
1319 |
|
// Load defaults |
|
1320 |
|
while (1) { |
|
1321 |
|
$rg['pay-squareup-bearer'] = rg_state_get($db, 'pay-squareup-bearer'); |
|
1322 |
|
$rg['pay-squareup-location_id'] = rg_state_get($db, 'pay-squareup-location_id'); |
|
1323 |
|
break; |
|
1324 |
|
} |
|
1325 |
|
|
|
1326 |
|
//$hints[]['HTML:hint'] = rg_template('admin/pay/squareup-hints.html', |
|
1327 |
|
// $rg, TRUE /*xss*/); |
|
1328 |
|
|
|
1329 |
|
$rg['HTML:hints'] = rg_template_table('hints/list', $hints, $rg); |
|
1330 |
|
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
1331 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'admin_pay_squareup_high_level'); |
|
1332 |
|
$ret .= rg_template('admin/pay/squareup.html', $rg, TRUE /*xss*/); |
|
1333 |
|
|
|
1334 |
|
rg_log_exit(); |
|
1335 |
|
return $ret; |
|
1336 |
|
} |
|
1337 |
|
|
File inc/plan.inc.php changed (mode: 100644) (index c443db4..51c0400) |
... |
... |
function rg_plan_edit($db, $d) |
46 |
46 |
break; |
break; |
47 |
47 |
|
|
48 |
48 |
if ($d['id'] == 0) { // add |
if ($d['id'] == 0) { // add |
49 |
|
$sql = "INSERT INTO plans (name, description, disk_mb" |
|
50 |
|
. ", users, bw, speed, position" |
|
51 |
|
. ", max_public_repos, max_private_repos)" |
|
52 |
|
. " VALUES (@@name@@, @@description@@" |
|
53 |
|
. ", @@disk_mb@@, @@users@@, @@bw@@" |
|
54 |
|
. ", @@speed@@, @@position@@" |
|
55 |
|
. ", @@max_public_repos@@, @@max_private_repos@@)" |
|
56 |
|
. " RETURNING id"; |
|
|
49 |
|
$sql = 'INSERT INTO plans (name, description, disk_mb' |
|
50 |
|
. ', users, bw, speed, position' |
|
51 |
|
. ', max_public_repos, max_private_repos' |
|
52 |
|
. ', prices)' |
|
53 |
|
. ' VALUES (@@name@@, @@description@@' |
|
54 |
|
. ', @@disk_mb@@, @@users@@, @@bw@@' |
|
55 |
|
. ', @@speed@@, @@position@@' |
|
56 |
|
. ', @@max_public_repos@@, @@max_private_repos@@' |
|
57 |
|
. ', @@prices@@)' |
|
58 |
|
. ' RETURNING id'; |
57 |
59 |
} else { // edit |
} else { // edit |
58 |
|
$sql = "UPDATE plans" |
|
59 |
|
. " SET name = @@name@@" |
|
60 |
|
. ", description = @@description@@" |
|
61 |
|
. ", disk_mb = @@disk_mb@@" |
|
62 |
|
. ", users = @@users@@" |
|
63 |
|
. ", bw = @@bw@@" |
|
64 |
|
. ", speed = @@speed@@" |
|
65 |
|
. ", position = @@position@@" |
|
66 |
|
. ", max_public_repos = @@max_public_repos@@" |
|
67 |
|
. ", max_private_repos = @@max_private_repos@@" |
|
68 |
|
. " WHERE id = @@id@@" |
|
69 |
|
. " RETURNING id"; |
|
|
60 |
|
$sql = 'UPDATE plans' |
|
61 |
|
. ' SET name = @@name@@' |
|
62 |
|
. ', description = @@description@@' |
|
63 |
|
. ', disk_mb = @@disk_mb@@' |
|
64 |
|
. ', users = @@users@@' |
|
65 |
|
. ', bw = @@bw@@' |
|
66 |
|
. ', speed = @@speed@@' |
|
67 |
|
. ', position = @@position@@' |
|
68 |
|
. ', max_public_repos = @@max_public_repos@@' |
|
69 |
|
. ', max_private_repos = @@max_private_repos@@' |
|
70 |
|
. ', prices = @@prices@@' |
|
71 |
|
. ' WHERE id = @@id@@' |
|
72 |
|
. ' RETURNING id'; |
70 |
73 |
} |
} |
71 |
74 |
|
|
72 |
75 |
$res = rg_sql_query_params($db, $sql, $d); |
$res = rg_sql_query_params($db, $sql, $d); |
|
... |
... |
function rg_plan_cosmetic(&$row) |
134 |
137 |
$_a = rg_xss_safe(trim($row['description'])); |
$_a = rg_xss_safe(trim($row['description'])); |
135 |
138 |
$row['HTML:description_nlbr'] = nl2br($_a); |
$row['HTML:description_nlbr'] = nl2br($_a); |
136 |
139 |
|
|
|
140 |
|
if (empty($row['prices'])) |
|
141 |
|
$row['prices_nice'] = 'No prices defined'; |
|
142 |
|
else |
|
143 |
|
$row['prices_nice'] = $row['prices']; |
|
144 |
|
|
137 |
145 |
$row['exists'] = 1; |
$row['exists'] = 1; |
138 |
146 |
} |
} |
139 |
147 |
|
|
|
... |
... |
function rg_plan_list($db) |
162 |
170 |
break; |
break; |
163 |
171 |
} |
} |
164 |
172 |
|
|
165 |
|
$sql = "SELECT * FROM plans ORDER BY position"; |
|
|
173 |
|
$sql = 'SELECT * FROM plans ORDER BY position, name'; |
166 |
174 |
$res = rg_sql_query($db, $sql); |
$res = rg_sql_query($db, $sql); |
167 |
175 |
if ($res === FALSE) { |
if ($res === FALSE) { |
168 |
176 |
rg_plan_set_error('cannot get plan list'); |
rg_plan_set_error('cannot get plan list'); |
|
... |
... |
function rg_plan_edit_high_level($db, &$rg) |
331 |
339 |
$pi['position'] = "100"; |
$pi['position'] = "100"; |
332 |
340 |
$pi['max_public_repos'] = "0"; |
$pi['max_public_repos'] = "0"; |
333 |
341 |
$pi['max_private_repos'] = "0"; |
$pi['max_private_repos'] = "0"; |
|
342 |
|
$pi['prices'] = ''; |
334 |
343 |
} |
} |
335 |
344 |
} |
} |
336 |
345 |
|
|
|
... |
... |
function rg_plan_edit_high_level($db, &$rg) |
351 |
360 |
$pi['position'] = rg_var_uint("pi::position"); |
$pi['position'] = rg_var_uint("pi::position"); |
352 |
361 |
$pi['max_public_repos'] = rg_var_uint("pi::max_public_repos"); |
$pi['max_public_repos'] = rg_var_uint("pi::max_public_repos"); |
353 |
362 |
$pi['max_private_repos'] = rg_var_uint("pi::max_private_repos"); |
$pi['max_private_repos'] = rg_var_uint("pi::max_private_repos"); |
|
363 |
|
$pi['prices'] = trim(rg_var_str("pi::prices")); |
354 |
364 |
|
|
355 |
365 |
if (!rg_valid_referer()) { |
if (!rg_valid_referer()) { |
356 |
366 |
$errmsg[] = "invalid referer; try again"; |
$errmsg[] = "invalid referer; try again"; |
|
... |
... |
function rg_plan_edit_high_level($db, &$rg) |
368 |
378 |
break; |
break; |
369 |
379 |
} |
} |
370 |
380 |
|
|
371 |
|
$ret .= rg_template("admin/plans/add_ok.html", $rg, TRUE /* xss */); |
|
|
381 |
|
$ret .= rg_template("admin/plans/add_ok.html", $rg, TRUE /*xss*/); |
372 |
382 |
$load_form = FALSE; |
$load_form = FALSE; |
373 |
383 |
break; |
break; |
374 |
384 |
} |
} |
|
... |
... |
function rg_plan_edit_high_level($db, &$rg) |
377 |
387 |
$rg['pi'] = $pi; |
$rg['pi'] = $pi; |
378 |
388 |
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
379 |
389 |
$rg['rg_form_token'] = rg_token_get($db, $rg, 'plan_edit_hl'); |
$rg['rg_form_token'] = rg_token_get($db, $rg, 'plan_edit_hl'); |
380 |
|
$ret .= rg_template("admin/plans/add_edit.html", $rg, TRUE /* xss */); |
|
|
390 |
|
$ret .= rg_template("admin/plans/add_edit.html", $rg, TRUE /*xss*/); |
381 |
391 |
} |
} |
382 |
392 |
|
|
383 |
393 |
return $ret; |
return $ret; |
File inc/struct.inc.php changed (mode: 100644) (index 03f33a5..1a5f424) |
... |
... |
$rg_sql_struct[49]['tables'] = array(); |
760 |
760 |
$rg_sql_struct[49]['other'] = array( |
$rg_sql_struct[49]['other'] = array( |
761 |
761 |
'repo_hash' => 'ALTER TABLE repos ADD hash TEXT DEFAULT \'sha1\'' |
'repo_hash' => 'ALTER TABLE repos ADD hash TEXT DEFAULT \'sha1\'' |
762 |
762 |
); |
); |
|
763 |
|
|
|
764 |
|
$rg_sql_struct[50]['tables'] = array( |
|
765 |
|
'payments' => 'CREATE TABLE payments (' |
|
766 |
|
. 'id CHAR(16) PRIMARY KEY' |
|
767 |
|
. ', uid INT NOT NULL' |
|
768 |
|
. ', itime INT NOT NULL' |
|
769 |
|
. ', type TEXT NOT NULL' |
|
770 |
|
. ', type_extra TEXT NOT NULL' |
|
771 |
|
. ', amount INT NOT NULL' |
|
772 |
|
. ', currency TEXT NOT NULL' |
|
773 |
|
. ', operator TEXT NOT NULL' |
|
774 |
|
. ', state TEXT NOT NULL' |
|
775 |
|
. ', order_id TEXT NOT NULL' |
|
776 |
|
. ', next_try INT NOT NULL)', |
|
777 |
|
'payments_history' => 'CREATE TABLE payments_history (' |
|
778 |
|
. 'itime INT NOT NULL' |
|
779 |
|
. ', uid INT NOT NULL' |
|
780 |
|
. ', pay_id CHAR(16) NOT NULL' |
|
781 |
|
. ', text TEXT NOT NULL)' |
|
782 |
|
); |
|
783 |
|
$rg_sql_struct[50]['other'] = array( |
|
784 |
|
'plan_prices' => 'ALTER TABLE plans ADD prices TEXT DEFAULT \'\'' |
|
785 |
|
); |
|
786 |
|
$rg_sql_struct_parts['payments_history'] = array(); |
763 |
787 |
// Here 0.77 was released |
// Here 0.77 was released |
764 |
788 |
|
|
765 |
|
// Do not forget to add the new created tables to statistics. |
|
|
789 |
|
// Do not forget to add the new created tables to statistics. Where? |
766 |
790 |
|
|
767 |
791 |
// The next line must be after all rg_sql_struct* definitions. |
// The next line must be after all rg_sql_struct* definitions. |
768 |
792 |
$rg_sql_schema_ver = count($rg_sql_struct); |
$rg_sql_schema_ver = count($rg_sql_struct); |
File inc/user.inc.php changed (mode: 100644) (index c34e2ad..51e07ab) |
... |
... |
require_once(__DIR__ . '/mail.inc.php'); |
10 |
10 |
require_once(__DIR__ . '/plan.inc.php'); |
require_once(__DIR__ . '/plan.inc.php'); |
11 |
11 |
require_once(__DIR__ . '/totp.inc.php'); |
require_once(__DIR__ . '/totp.inc.php'); |
12 |
12 |
require_once(__DIR__ . '/stats.inc.php'); |
require_once(__DIR__ . '/stats.inc.php'); |
|
13 |
|
require_once(__DIR__ . '/user/pay/main.inc.php'); |
13 |
14 |
|
|
14 |
15 |
$rg_user_rights = array( |
$rg_user_rights = array( |
15 |
16 |
"C" => "Create repository", |
"C" => "Create repository", |
|
... |
... |
function rg_user_edit_high_level($db, $rg) |
2160 |
2161 |
// TODO: should we just redirect to login page? |
// TODO: should we just redirect to login page? |
2161 |
2162 |
// TODO: or to user page if there is no need to confirm the account? |
// TODO: or to user page if there is no need to confirm the account? |
2162 |
2163 |
if ($ui['uid'] == 0) |
if ($ui['uid'] == 0) |
2163 |
|
$ret = rg_template("user/create_ok.html", $rg, TRUE /* xss */); |
|
|
2164 |
|
$ret = rg_template('user/create_ok.html', $rg, TRUE /*xss*/); |
2164 |
2165 |
else |
else |
2165 |
|
$ret = rg_template("user/edit_ok.html", $rg, TRUE /* xss */); |
|
|
2166 |
|
$ret = rg_template('user/edit_ok.html', $rg, TRUE /*xss*/); |
|
2167 |
|
|
|
2168 |
|
$ret .= rg_pay_needed_high_level($db, $rg); |
|
2169 |
|
|
2166 |
2170 |
$load_form = FALSE; |
$load_form = FALSE; |
2167 |
2171 |
break; |
break; |
2168 |
2172 |
} |
} |
File inc/user/home-page.php changed (mode: 100644) (index 42c2743..fe92104) |
1 |
1 |
<?php |
<?php |
2 |
2 |
$_home = ''; |
$_home = ''; |
3 |
3 |
|
|
|
4 |
|
$ui_login = rg_ui_login(); |
|
5 |
|
|
4 |
6 |
$ui_page = rg_user_info($db, 0, $user, ''); |
$ui_page = rg_user_info($db, 0, $user, ''); |
5 |
7 |
if (($ui_page['exists'] == 0) || ($ui_page['suspended'] > 0) |
if (($ui_page['exists'] == 0) || ($ui_page['suspended'] > 0) |
6 |
8 |
|| ($ui_page['deleted'] > 0)) { |
|| ($ui_page['deleted'] > 0)) { |
|
... |
... |
if (($ui_page['exists'] == 0) || ($ui_page['suspended'] > 0) |
9 |
11 |
} |
} |
10 |
12 |
rg_ui_page_set($ui_page); |
rg_ui_page_set($ui_page); |
11 |
13 |
|
|
12 |
|
rg_watch_hl_process($db, $rg, 'user', $ui_page['uid'], 0, $rg['current_url']); |
|
|
14 |
|
rg_watch_hl_process($db, $rg, 'user', $ui_page['uid'], 0, $rg['current_url_esc']); |
13 |
15 |
|
|
14 |
16 |
$_home .= rg_template('user/home.html', $rg, TRUE /*xss*/); |
$_home .= rg_template('user/home.html', $rg, TRUE /*xss*/); |
15 |
17 |
|
|
|
18 |
|
$pay_id = rg_var_re('paid', 'A-Za-z0-9'); |
|
19 |
|
if (!empty($pay_id)) { |
|
20 |
|
$_home .= rg_pay_done_high_level($db, $rg, $pay_id); |
|
21 |
|
} else { |
|
22 |
|
// If payment is needed, ask the user to pay |
|
23 |
|
$_home .= rg_pay_needed_high_level($db, $rg); |
|
24 |
|
} |
|
25 |
|
|
16 |
26 |
// List of repositories |
// List of repositories |
17 |
27 |
$_home .= rg_repo_list($db, $rg, '', $ui_page['uid'], 0); |
$_home .= rg_repo_list($db, $rg, '', $ui_page['uid'], 0); |
18 |
28 |
|
|
|
... |
... |
$_home .= rg_repo_list($db, $rg, '', $ui_page['uid'], 0); |
20 |
30 |
// hints |
// hints |
21 |
31 |
$hints = array(); |
$hints = array(); |
22 |
32 |
|
|
23 |
|
$ui_login = rg_ui_login(); |
|
24 |
33 |
if ($ui_page['uid'] == $ui_login['uid']) { |
if ($ui_page['uid'] == $ui_login['uid']) { |
25 |
34 |
if (empty($ui_login['email'])) |
if (empty($ui_login['email'])) |
26 |
35 |
$hints[]['HTML:hint'] = rg_template('user/hints/empty_email.html', |
$hints[]['HTML:hint'] = rg_template('user/hints/empty_email.html', |
File inc/user/pay/main.inc.php added (mode: 100644) (index 0000000..473d26d) |
|
1 |
|
<?php |
|
2 |
|
include_once(__DIR__ . '/pay-core.inc.php'); |
|
3 |
|
include_once(__DIR__ . '/squareup.inc.php'); |
|
4 |
|
|
|
5 |
|
/* |
|
6 |
|
* Generates the payment page |
|
7 |
|
*/ |
|
8 |
|
function rg_pay_generate_pay_page($db, $rg, $prices) |
|
9 |
|
{ |
|
10 |
|
do { |
|
11 |
|
$rg['pay']['HTML:prices_select'] = rg_pay_prices_select($prices); |
|
12 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'user_pay'); |
|
13 |
|
$rg['errmsg'] = ''; |
|
14 |
|
$rg['pay_hints'] = ''; |
|
15 |
|
return rg_template('user/pay/form.html', $rg, TRUE /*xss*/); |
|
16 |
|
} while (0); |
|
17 |
|
} |
|
18 |
|
|
|
19 |
|
/* |
|
20 |
|
* Check if user needs to pay and if needed invite her to pay |
|
21 |
|
*/ |
|
22 |
|
function rg_pay_needed_high_level($db, $rg) |
|
23 |
|
{ |
|
24 |
|
rg_log_enter('pay_needed_high_level'); |
|
25 |
|
|
|
26 |
|
$ret = ''; |
|
27 |
|
do { |
|
28 |
|
$ui_login = rg_ui_login(); |
|
29 |
|
if ($ui_login['uid'] == 0) |
|
30 |
|
break; |
|
31 |
|
|
|
32 |
|
// TODO: not good! The user may want to switch plans |
|
33 |
|
$plan_id = $ui_login['plan_id']; |
|
34 |
|
|
|
35 |
|
$pi = rg_plan_info($db, $plan_id); |
|
36 |
|
if ($pi['ok'] != 1) { |
|
37 |
|
$ret = rg_template('generr.html', $rg, TRUE /*xss*/); |
|
38 |
|
break; |
|
39 |
|
} |
|
40 |
|
if (empty($pi['prices'])) |
|
41 |
|
break; |
|
42 |
|
|
|
43 |
|
$rg['pi'] = $pi; |
|
44 |
|
|
|
45 |
|
$doit = rg_var_uint('pay-doit'); |
|
46 |
|
if ($doit == 1) { |
|
47 |
|
// Re-validate plan_id/price |
|
48 |
|
// TODO: create payment link |
|
49 |
|
|
|
50 |
|
$new_plan_id = rg_var_uint('plan_id'); |
|
51 |
|
rg_log_debug('new_plan_id=' . $new_plan_id); |
|
52 |
|
|
|
53 |
|
$new_pi = rg_plan_info($db, $plan_id); |
|
54 |
|
if ($new_pi['ok'] != 1) { |
|
55 |
|
$ret = rg_template('generr.html', $rg, TRUE /*xss*/); |
|
56 |
|
break; |
|
57 |
|
} |
|
58 |
|
if (empty($new_pi['prices'])) |
|
59 |
|
break; |
|
60 |
|
|
|
61 |
|
$option = rg_var_str('currency_amount'); |
|
62 |
|
rg_log_debug('option=' . $option); |
|
63 |
|
$t = explode('/', $option); |
|
64 |
|
$ym = strcmp($t[0], 'y') == 0 ? 'y' : 'm'; |
|
65 |
|
$amount = intval($t[1]); |
|
66 |
|
$currency = preg_replace('/[^A-Za-z]/', '', $t[2]); |
|
67 |
|
$data = array('name' => 'plan ' . $new_pi['name'], |
|
68 |
|
'type' => 'plan', |
|
69 |
|
'type_id' => $new_plan_id, |
|
70 |
|
'interval' => $ym, |
|
71 |
|
'amount' => $amount, |
|
72 |
|
'currency' => $currency |
|
73 |
|
); |
|
74 |
|
$r = rg_pay_square_create_link($db, $data); |
|
75 |
|
if ($r['ok'] != 1) { |
|
76 |
|
$ret = rg_template('user/pay/link-err.html', $rg, TRUE /*xss*/); |
|
77 |
|
break; |
|
78 |
|
} |
|
79 |
|
|
|
80 |
|
rg_log_debug('Redirecting to ' . $r['redirect']); |
|
81 |
|
rg_redirect($r['redirect']); |
|
82 |
|
} |
|
83 |
|
|
|
84 |
|
$rg['pay'] = array(); |
|
85 |
|
|
|
86 |
|
$pay = rg_pay_user_info($db, $ui_login['uid']); |
|
87 |
|
if ($pay['ok'] != 1) { |
|
88 |
|
$ret = rg_template('generr.html', $rg, TRUE /*xss*/); |
|
89 |
|
break; |
|
90 |
|
} |
|
91 |
|
|
|
92 |
|
if (empty($pay['list'])) { |
|
93 |
|
$ret = rg_pay_generate_pay_page($db, $rg, $pi['prices']); |
|
94 |
|
break; |
|
95 |
|
} |
|
96 |
|
|
|
97 |
|
// TODO: check if the last payment covers 'now' |
|
98 |
|
|
|
99 |
|
$ret = rg_pay_generate_pay_page($db, $rg, $pi['prices']); |
|
100 |
|
} while (0); |
|
101 |
|
|
|
102 |
|
rg_log_exit(); |
|
103 |
|
return $ret; |
|
104 |
|
} |
|
105 |
|
|
|
106 |
|
/* |
|
107 |
|
* Check if user needs to pay and if needed invite her to pay |
|
108 |
|
*/ |
|
109 |
|
function rg_pay_done_high_level($db, $rg, $pay_id) |
|
110 |
|
{ |
|
111 |
|
$ret = ''; |
|
112 |
|
do { |
|
113 |
|
if (strlen($pay_id) != 16) |
|
114 |
|
break; |
|
115 |
|
|
|
116 |
|
// TODO: mark the payment as 'redirected' to not bother the user after payment |
|
117 |
|
// TODO: schedule event to check the payment |
|
118 |
|
$rg['pay_id'] = $pay_id; |
|
119 |
|
$ret = rg_template('user/pay/redir.html', $rg, TRUE /*xss*/); |
|
120 |
|
} while (0); |
|
121 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
122 |
|
|
|
123 |
|
return $ret; |
|
124 |
|
} |
|
125 |
|
|
|
126 |
|
/* |
|
127 |
|
* Checks if initiated transactions are paid |
|
128 |
|
*/ |
|
129 |
|
function rg_pay_update_orders_states($db) |
|
130 |
|
{ |
|
131 |
|
rg_log_enter('pay_update_orders_states'); |
|
132 |
|
|
|
133 |
|
$ret = array('ok' => 0); |
|
134 |
|
do { |
|
135 |
|
$now = time(); |
|
136 |
|
$params = array('state' => 'init', 'now' => $now); |
|
137 |
|
$sql = 'SELECT * FROM payments' |
|
138 |
|
. ' WHERE state = @@state@@' |
|
139 |
|
. ' AND next_try < @@now@@' |
|
140 |
|
. ' ORDER BY next_try' |
|
141 |
|
. ' LIMIT 100'; |
|
142 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
143 |
|
if ($res === FALSE) { |
|
144 |
|
$ret['errmsg'] = rg_sql_error(); |
|
145 |
|
break; |
|
146 |
|
} |
|
147 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
148 |
|
rg_log_debug('Processing row: ' . print_r($row, TRUE)); |
|
149 |
|
|
|
150 |
|
$next = time() + 24 * 3600; // TODO: configurable? |
|
151 |
|
$r = rg_pay_update_next_try($db, $row['id'], $next); |
|
152 |
|
if ($r['ok'] != 1) { |
|
153 |
|
$ret['errmsg'] = $r['errmsg']; |
|
154 |
|
break; |
|
155 |
|
} |
|
156 |
|
|
|
157 |
|
$operator = $row['operator']; unset($row['operator']); |
|
158 |
|
if (strcmp($operator, 'squareup') == 0) { |
|
159 |
|
$r = rg_pay_square_update_order_state($db, $row); |
|
160 |
|
} else { |
|
161 |
|
$r['ok'] = 0; |
|
162 |
|
$r['errmsg'] = 'invalid operator ' . $operator; |
|
163 |
|
rg_internal_error($r['errmsg']); |
|
164 |
|
} |
|
165 |
|
if ($r['ok'] != 1) { |
|
166 |
|
$ret['errmsg'] = $r['errmsg']; |
|
167 |
|
break; |
|
168 |
|
} |
|
169 |
|
} |
|
170 |
|
rg_sql_free_result($res); |
|
171 |
|
if (isset($ret['errmsg'])) |
|
172 |
|
break; |
|
173 |
|
|
|
174 |
|
$ret['ok'] = 1; |
|
175 |
|
} while (0); |
|
176 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
177 |
|
|
|
178 |
|
rg_log_exit(); |
|
179 |
|
return $ret; |
|
180 |
|
} |
File inc/user/pay/pay-core.inc.php added (mode: 100644) (index 0000000..86eff4e) |
|
1 |
|
<?php |
|
2 |
|
include_once(__DIR__ . '/squareup.inc.php'); |
|
3 |
|
|
|
4 |
|
/* |
|
5 |
|
* Returns information about the paid account |
|
6 |
|
*/ |
|
7 |
|
function rg_pay_user_info($db, $uid) |
|
8 |
|
{ |
|
9 |
|
rg_prof_start('pay_user_info'); |
|
10 |
|
rg_log_enter('pay_user_info'); |
|
11 |
|
|
|
12 |
|
$ret = array('ok' => 0); |
|
13 |
|
do { |
|
14 |
|
$params = array('uid' => $uid); |
|
15 |
|
$sql = 'SELECT * FROM payments WHERE uid = @@uid@@' |
|
16 |
|
. ' ORDER BY itime DESC' |
|
17 |
|
. ' LIMIT 10'; |
|
18 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
19 |
|
if ($res === FALSE) { |
|
20 |
|
$ret['errmsg'] = 'cannot load payments'; |
|
21 |
|
break; |
|
22 |
|
} |
|
23 |
|
|
|
24 |
|
$ret['list'] = array(); |
|
25 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
26 |
|
$id = $row['id']; unset($row['id']); |
|
27 |
|
$ret['list'][$id] = $row; |
|
28 |
|
} |
|
29 |
|
rg_sql_free_result($res); |
|
30 |
|
|
|
31 |
|
$ret['ok'] = 1; |
|
32 |
|
} while (0); |
|
33 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
34 |
|
|
|
35 |
|
rg_log_exit(); |
|
36 |
|
rg_prof_end('pay_user_info'); |
|
37 |
|
return $ret; |
|
38 |
|
} |
|
39 |
|
|
|
40 |
|
/* |
|
41 |
|
* Transforms a space separated list of currencies into a select |
|
42 |
|
*/ |
|
43 |
|
function rg_pay_prices_select($prices) |
|
44 |
|
{ |
|
45 |
|
$ret = '<select name="currency_amount" id="currency_amount">' . "\n"; $add = ''; |
|
46 |
|
$x = explode(' ', $prices); |
|
47 |
|
foreach ($x as $p) { |
|
48 |
|
$t = explode('/', $p); |
|
49 |
|
$per_month = trim($t[0]); |
|
50 |
|
$per_year = trim($t[1]); |
|
51 |
|
$currency = $t[2]; |
|
52 |
|
|
|
53 |
|
$text = $per_year . ' ' . $currency . ' / year'; |
|
54 |
|
$ret .= $add . '<option value="y/' . $per_year . '/' . $currency . '">' . $text . '</option>'; |
|
55 |
|
$add = "\n\t"; |
|
56 |
|
|
|
57 |
|
$text = $per_month . ' ' . $currency . ' / month'; |
|
58 |
|
$ret .= $add . '<option value="m/' . $per_month . '/' . $currency . '">' . $text . '</option>'; |
|
59 |
|
$add = "\n\t"; |
|
60 |
|
} |
|
61 |
|
|
|
62 |
|
$ret .= "\n" . '</select>'; |
|
63 |
|
|
|
64 |
|
return $ret; |
|
65 |
|
} |
|
66 |
|
|
|
67 |
|
/* |
|
68 |
|
* Adds an entry in the payment history |
|
69 |
|
*/ |
|
70 |
|
function rg_pay_history(int $db, int $uid, string $pay_id, array $info) |
|
71 |
|
{ |
|
72 |
|
rg_log_enter('pay_history: pay_id=' . $pay_id); |
|
73 |
|
|
|
74 |
|
$ret = array('ok' => 0); |
|
75 |
|
do { |
|
76 |
|
$now = time(); |
|
77 |
|
$params = array('uid' => $uid, 'now' => $now, |
|
78 |
|
'pay_id' => $pay_id, 'text' => json_encode($info)); |
|
79 |
|
$sql = 'INSERT INTO payments_history_' . gmdate('Y_m', $now) |
|
80 |
|
. '(pay_id, uid, itime, text)' |
|
81 |
|
. ' VALUES(@@pay_id@@, @@uid@@, @@now@@, @@text@@)'; |
|
82 |
|
$r = rg_sql_query_params($db, $sql, $params); |
|
83 |
|
if ($r === FALSE) { |
|
84 |
|
$ret['errmsg'] = rg_sql_error(); |
|
85 |
|
break; |
|
86 |
|
} |
|
87 |
|
|
|
88 |
|
$ret['ok'] = 1; |
|
89 |
|
} while (0); |
|
90 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
91 |
|
|
|
92 |
|
rg_log_exit(); |
|
93 |
|
return $ret; |
|
94 |
|
} |
|
95 |
|
|
|
96 |
|
/* |
|
97 |
|
* Adds a payment |
|
98 |
|
* @type: 'plan' |
|
99 |
|
* @type_extra[plan]: 'y' (=yearly) or 'm' (= monthly) |
|
100 |
|
*/ |
|
101 |
|
function rg_pay_insert($db, $data) |
|
102 |
|
{ |
|
103 |
|
rg_log_enter('pay_insert: data=' . rg_array2string($data)); |
|
104 |
|
|
|
105 |
|
$ret = array('ok' => 0); |
|
106 |
|
do { |
|
107 |
|
// TODO: transaction? |
|
108 |
|
$data['itime'] = time(); |
|
109 |
|
$data['next_try'] = 0; |
|
110 |
|
$sql = 'INSERT INTO payments (id, uid, operator' |
|
111 |
|
. ', itime, type, type_id, type_extra' |
|
112 |
|
. ', amount, currency, state' |
|
113 |
|
. ', order_id, next_try)' |
|
114 |
|
. ' VALUES (@@pay_id@@, @@uid@@, @@operator@@' |
|
115 |
|
. ', @@itime@@, @@type@@, @@type_id@@, @@interval@@' |
|
116 |
|
. ', @@amount@@, @@currency@@, @@state@@' |
|
117 |
|
. ', @@order_id@@, @@next_try@@)'; |
|
118 |
|
$r = rg_sql_query_params($db, $sql, $data); |
|
119 |
|
if ($r === FALSE) { |
|
120 |
|
$ret['errmsg'] = rg_sql_error(); |
|
121 |
|
break; |
|
122 |
|
} |
|
123 |
|
|
|
124 |
|
$r = rg_pay_history($db, $data['uid'], $data['pay_id'], |
|
125 |
|
array('ok' => 1, 'text' => 'Payment created')); |
|
126 |
|
if ($r['ok'] != 1) { |
|
127 |
|
$ret['errmsg'] = $r['errmsg']; |
|
128 |
|
break; |
|
129 |
|
} |
|
130 |
|
|
|
131 |
|
$ret['ok'] = 1; |
|
132 |
|
} while (0); |
|
133 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
134 |
|
|
|
135 |
|
rg_log_exit(); |
|
136 |
|
return $ret; |
|
137 |
|
} |
|
138 |
|
|
|
139 |
|
/* |
|
140 |
|
* Update internal state of an order |
|
141 |
|
*/ |
|
142 |
|
function rg_pay_update_order_state(int $db, int $uid, string $pay_id, |
|
143 |
|
string $state) |
|
144 |
|
{ |
|
145 |
|
rg_log_enter('pay_update_order_state: uid=' . $uid |
|
146 |
|
. ' pay_id=' . $pay_id . ' state=' . $state); |
|
147 |
|
|
|
148 |
|
$ret = array('ok' => 0); |
|
149 |
|
do { |
|
150 |
|
$params = array('uid' => $uid, 'pay_id' => $pay_id, |
|
151 |
|
'state' => $state); |
|
152 |
|
$sql = 'UPDATE payments SET state = @@state@@' |
|
153 |
|
. ' WHERE uid = @@uid@@ AND pay_id = @@pay_id@@'; |
|
154 |
|
$r = rg_sql_query_params($db, $sql, $data); |
|
155 |
|
if ($r === FALSE) { |
|
156 |
|
$ret['errmsg'] = rg_sql_error(); |
|
157 |
|
break; |
|
158 |
|
} |
|
159 |
|
|
|
160 |
|
$j = array('ok' => 1, |
|
161 |
|
'text' => 'order_id state changed to ' . $state); |
|
162 |
|
$r = rg_pay_history($db, $uid, $pay_id, $j); |
|
163 |
|
if ($r['ok'] != 1) { |
|
164 |
|
$ret['errmsg'] = $r['errmsg']; |
|
165 |
|
break; |
|
166 |
|
} |
|
167 |
|
|
|
168 |
|
$ret['ok'] = 1; |
|
169 |
|
} while (0); |
|
170 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
171 |
|
|
|
172 |
|
rg_log_exit(); |
|
173 |
|
return $ret; |
|
174 |
|
} |
|
175 |
|
|
|
176 |
|
/* |
|
177 |
|
* Update next_try (to prevent flooding the operator |
|
178 |
|
*/ |
|
179 |
|
function rg_pay_update_next_try(int $db, string $pay_id, int $next) |
|
180 |
|
{ |
|
181 |
|
rg_log_enter('pay_update_next_try: pay_id=' . $pay_id . ' next=' . $next); |
|
182 |
|
|
|
183 |
|
$ret = array('ok' => 0); |
|
184 |
|
do { |
|
185 |
|
// TODO: transaction? |
|
186 |
|
|
|
187 |
|
$params = array('pay_id' => $pay_id, 'next_try' => $next); |
|
188 |
|
$sql = 'UPDATE payments SET next_try = @@next_try@@' |
|
189 |
|
. ' WHERE id = @@pay_id@@'; |
|
190 |
|
$r = rg_sql_query_params($db, $sql, $params); |
|
191 |
|
if ($r === FALSE) { |
|
192 |
|
$ret['errmsg'] = rg_sql_error(); |
|
193 |
|
break; |
|
194 |
|
} |
|
195 |
|
|
|
196 |
|
$ret['ok'] = 1; |
|
197 |
|
} while (0); |
|
198 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
199 |
|
|
|
200 |
|
rg_log_exit(); |
|
201 |
|
return $ret; |
|
202 |
|
} |
|
203 |
|
|
File inc/user/pay/squareup.inc.php added (mode: 100644) (index 0000000..d61f919) |
|
1 |
|
<?php |
|
2 |
|
// Here are the Square UP functions |
|
3 |
|
|
|
4 |
|
include_once(__DIR__ . '/pay-core.inc.php'); |
|
5 |
|
|
|
6 |
|
$rg_pay_square_url = 'https://connect.squareupsandbox.com'; |
|
7 |
|
|
|
8 |
|
function rg_pay_square_request(int $db, string $url, array $body) |
|
9 |
|
{ |
|
10 |
|
global $rg_pay_square_url; |
|
11 |
|
|
|
12 |
|
rg_prof_start('pay_square_request'); |
|
13 |
|
rg_log_enter('pay_square_request'); |
|
14 |
|
|
|
15 |
|
$ret = array('ok' => 0); |
|
16 |
|
do { |
|
17 |
|
$bearer = rg_state_get($db, 'pay-squareup-bearer'); |
|
18 |
|
|
|
19 |
|
if (!empty($body)) |
|
20 |
|
rg_log_debug('body: ' . print_r($body, TRUE)); |
|
21 |
|
|
|
22 |
|
$headers = array(); |
|
23 |
|
$headers[] = 'Content-Type: application/json'; |
|
24 |
|
$headers[] = 'Square-Version: 2022-12-14'; |
|
25 |
|
$headers[] = 'Authorization: Bearer ' . $bearer; |
|
26 |
|
|
|
27 |
|
$c = curl_init($rg_pay_square_url . $url); |
|
28 |
|
if (!empty($body)) { |
|
29 |
|
curl_setopt($c, CURLOPT_POST, 1); |
|
30 |
|
curl_setopt($c, CURLOPT_POSTFIELDS, json_encode($body)); |
|
31 |
|
} |
|
32 |
|
curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE); |
|
33 |
|
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1); |
|
34 |
|
curl_setopt($c, CURLOPT_HEADER, 1); |
|
35 |
|
curl_setopt($c, CURLOPT_HTTPHEADER, $headers); |
|
36 |
|
curl_setopt($c, CURLOPT_USERAGENT, 'RocketGit WebPay'); |
|
37 |
|
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 30); |
|
38 |
|
curl_setopt($c, CURLOPT_ENCODING, ''); // => use all methods |
|
39 |
|
curl_setopt($c, CURLOPT_VERBOSE, TRUE); |
|
40 |
|
curl_setopt($c, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); |
|
41 |
|
|
|
42 |
|
$err = @fopen('php://temp', 'w'); |
|
43 |
|
if ($err !== FALSE) |
|
44 |
|
curl_setopt($c, CURLOPT_STDERR, $err); |
|
45 |
|
|
|
46 |
|
$r = @curl_exec($c); |
|
47 |
|
if ($err !== FALSE) { |
|
48 |
|
rewind($err); |
|
49 |
|
$ret['err_extra'] = @fread($err, 16 * 4096); |
|
50 |
|
fclose($err); |
|
51 |
|
//rg_log_debug('err_extra: ' . $ret['err_extra']); |
|
52 |
|
} |
|
53 |
|
|
|
54 |
|
if ($r === FALSE) { |
|
55 |
|
$ret['errmsg'] = curl_error($c); |
|
56 |
|
break; |
|
57 |
|
} |
|
58 |
|
|
|
59 |
|
$_x = explode("\r\n\r\n", $r, 2); |
|
60 |
|
$ret['headers'] = $_x[0]; |
|
61 |
|
$t = @json_decode($_x[1], TRUE); |
|
62 |
|
if (empty($t)) { |
|
63 |
|
rg_internal_error('cannot decode squareup json' |
|
64 |
|
. ' [' . $_x[1] . ']: ' . json_last_error_msg()); |
|
65 |
|
$ret['errmsg'] = 'cannot decode json' . json_last_error_msg(); |
|
66 |
|
break; |
|
67 |
|
} |
|
68 |
|
$ret['body'] = $t; |
|
69 |
|
$ret['curl_info'] = @curl_getinfo($c); |
|
70 |
|
//rg_log('curl_getinfo: ' . rg_array2string($ret['curl_info'])); |
|
71 |
|
//rg_log_debug('Answer: ' . print_r($ret, TRUE)); |
|
72 |
|
$ret['ok'] = 1; |
|
73 |
|
} while (0); |
|
74 |
|
curl_close($c); |
|
75 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
76 |
|
|
|
77 |
|
rg_log_exit(); |
|
78 |
|
rg_prof_end('pay_square_request'); |
|
79 |
|
return $ret; |
|
80 |
|
} |
|
81 |
|
|
|
82 |
|
function rg_pay_square_create_link(int $db, array $data) |
|
83 |
|
{ |
|
84 |
|
global $rg_pay_square_url; |
|
85 |
|
|
|
86 |
|
rg_prof_start('pay_square_create_link'); |
|
87 |
|
rg_log_enter('pay_square_create_link'); |
|
88 |
|
|
|
89 |
|
$ret = array('ok' => 0); |
|
90 |
|
do { |
|
91 |
|
$location_id = rg_state_get($db, 'pay-squareup-location_id'); |
|
92 |
|
|
|
93 |
|
$ui_login = rg_ui_login(); |
|
94 |
|
|
|
95 |
|
$pay_id = rg_id(16); |
|
96 |
|
$body = array( |
|
97 |
|
'idempotency_key' => $pay_id, |
|
98 |
|
'quick_pay' => array( |
|
99 |
|
'location_id' => $location_id, |
|
100 |
|
'name' => $data['name'], |
|
101 |
|
'price_money' => array( |
|
102 |
|
'amount' => $data['amount'], |
|
103 |
|
'currency' => $data['currency'] |
|
104 |
|
) |
|
105 |
|
), |
|
106 |
|
'checkout_options' => array( |
|
107 |
|
'redirect_url' => rg_base_url($db, '', '') |
|
108 |
|
. rg_re_userpage($ui_login) . '?paid=' . $pay_id |
|
109 |
|
) |
|
110 |
|
); |
|
111 |
|
|
|
112 |
|
$r = rg_pay_square_request($db, |
|
113 |
|
'/v2/online-checkout/payment-links', |
|
114 |
|
$body); |
|
115 |
|
if ($r['ok'] != 1) { |
|
116 |
|
$ret = $r; |
|
117 |
|
break; |
|
118 |
|
} |
|
119 |
|
|
|
120 |
|
$url = @$r['body']['payment_link']['url']; |
|
121 |
|
if (empty($url)) { |
|
122 |
|
$ret['errmsg'] = 'no payment link'; |
|
123 |
|
break; |
|
124 |
|
} |
|
125 |
|
|
|
126 |
|
$order_id = @$r['body']['payment_link']['order_id']; |
|
127 |
|
if (empty($order_id)) { |
|
128 |
|
$ret['errmsg'] = 'no order_id'; |
|
129 |
|
break; |
|
130 |
|
} |
|
131 |
|
|
|
132 |
|
// Now, prepare the information on our side |
|
133 |
|
// TODO: need to store also the id from Square? |
|
134 |
|
$data['uid'] = $ui_login['uid']; |
|
135 |
|
$data['pay_id'] = $pay_id; |
|
136 |
|
$data['operator'] = 'squareup'; |
|
137 |
|
$data['state'] = 'init'; |
|
138 |
|
$data['order_id'] = $order_id; |
|
139 |
|
$r = rg_pay_insert($db, $data); |
|
140 |
|
if ($r['ok'] != 1) { |
|
141 |
|
$ret = $r; |
|
142 |
|
break; |
|
143 |
|
} |
|
144 |
|
|
|
145 |
|
$ret['redirect'] = $url; |
|
146 |
|
|
|
147 |
|
$ret['ok'] = 1; |
|
148 |
|
} while (0); |
|
149 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
150 |
|
|
|
151 |
|
rg_log_exit(); |
|
152 |
|
rg_prof_end('pay_square_create_link'); |
|
153 |
|
return $ret; |
|
154 |
|
} |
|
155 |
|
|
|
156 |
|
function rg_pay_square_get_order_info(int $db, int $uid, |
|
157 |
|
string $pay_id, string $order_id) |
|
158 |
|
{ |
|
159 |
|
global $rg_pay_square_url; |
|
160 |
|
|
|
161 |
|
rg_prof_start('pay_square_get_order_info'); |
|
162 |
|
rg_log_enter('pay_square_get_order_info'); |
|
163 |
|
|
|
164 |
|
$ret = array('ok' => 0); |
|
165 |
|
do { |
|
166 |
|
$body = array(); |
|
167 |
|
$r = rg_pay_square_request($db, |
|
168 |
|
'/v2/orders/' . $order_id, |
|
169 |
|
$body); |
|
170 |
|
rg_pay_history($db, $uid, $pay_id, $r); |
|
171 |
|
if ($r['ok'] != 1) { |
|
172 |
|
$ret = $r; |
|
173 |
|
break; |
|
174 |
|
} |
|
175 |
|
if ($r['curl_info']['http_code'] != 200) { |
|
176 |
|
$ret['errmsg'] = 'http code ' . $r['curl_info']['http_code'] . ' != 200'; |
|
177 |
|
break; |
|
178 |
|
} |
|
179 |
|
$ret['body'] = $r['body']; |
|
180 |
|
|
|
181 |
|
//rg_log_debug('order info: ' . print_r($r, TRUE)); |
|
182 |
|
$ret['ok'] = 1; |
|
183 |
|
} while (0); |
|
184 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
185 |
|
|
|
186 |
|
rg_log_exit(); |
|
187 |
|
rg_prof_end('pay_square_get_order_info'); |
|
188 |
|
return $ret; |
|
189 |
|
} |
|
190 |
|
|
|
191 |
|
function rg_pay_square_update_order_state(int $db, array $info) |
|
192 |
|
{ |
|
193 |
|
rg_log_enter('pay_square_update_order_state'); |
|
194 |
|
|
|
195 |
|
$ret = array('ok' => 1); |
|
196 |
|
do { |
|
197 |
|
$r = rg_pay_square_get_order_info($db, |
|
198 |
|
$info['uid'], $info['id'], $info['order_id']); |
|
199 |
|
rg_log_debug('get_order_info returned r[ok]=' . $r['ok']); |
|
200 |
|
if ($r['ok'] != 1) { |
|
201 |
|
$ret['ok'] = 0; |
|
202 |
|
$ret['errmsg'] = $r['errmsg']; |
|
203 |
|
break; |
|
204 |
|
} |
|
205 |
|
|
|
206 |
|
// update state if needed |
|
207 |
|
rg_log_debug('order: ' . print_r($r['body']['order'], TRUE)); |
|
208 |
|
$state = @$r['body']['order']['state']; |
|
209 |
|
if (empty($state)) { |
|
210 |
|
$ret['ok'] = 0; |
|
211 |
|
$ret['errmsg'] = 'body/order/state is empty'; |
|
212 |
|
break; |
|
213 |
|
} |
|
214 |
|
rg_log_debug('state: ' . $state); |
|
215 |
|
$new_state = ''; |
|
216 |
|
if (strcmp($state, 'COMPLETED') == 0) |
|
217 |
|
$new_state = 'paid'; |
|
218 |
|
else if (strcmp($state, 'CANCELED') == 0) |
|
219 |
|
$new_state = 'canceled'; |
|
220 |
|
if (!empty($new_state)) { |
|
221 |
|
$r = rg_pay_update_order_state($db, $info['uid'], |
|
222 |
|
$info['id'], $new_state); |
|
223 |
|
if ($r['ok'] != 1) { |
|
224 |
|
$ret['ok'] = 0; |
|
225 |
|
$ret['errmsg'] = $r['errmsg']; |
|
226 |
|
break; |
|
227 |
|
} |
|
228 |
|
} |
|
229 |
|
} while (0); |
|
230 |
|
if ($ret['ok'] != 1) rg_log_debug('error: ' . $ret['errmsg']); |
|
231 |
|
|
|
232 |
|
rg_log_exit(); |
|
233 |
|
return $ret; |
|
234 |
|
} |
File scripts/builder.php changed (mode: 100644) (index e26fa6a..ad00709) |
... |
... |
function rg_process_job($db, &$job) |
761 |
761 |
//rg_log_debug('workers list: ' . rg_array2string($workers_list)); |
//rg_log_debug('workers list: ' . rg_array2string($workers_list)); |
762 |
762 |
|
|
763 |
763 |
// Trying to find a worker in the list of connections |
// Trying to find a worker in the list of connections |
764 |
|
$reason = ''; |
|
|
764 |
|
$reason = array(); |
765 |
765 |
foreach ($rg_conns as $key => &$i) { |
foreach ($rg_conns as $key => &$i) { |
766 |
766 |
if (strcmp($key, 'master') == 0) |
if (strcmp($key, 'master') == 0) |
767 |
767 |
continue; |
continue; |
|
... |
... |
function rg_process_job($db, &$job) |
769 |
769 |
if (!isset($i['ann'])) { |
if (!isset($i['ann'])) { |
770 |
770 |
//rg_log($key . ': ' . $jid . ': conn has no announce.'); |
//rg_log($key . ': ' . $jid . ': conn has no announce.'); |
771 |
771 |
// TODO: close after some time? |
// TODO: close after some time? |
772 |
|
$reason .= 'A'; |
|
|
772 |
|
$reason[] = 'no_announce'; |
773 |
773 |
continue; |
continue; |
774 |
774 |
} |
} |
775 |
775 |
|
|
776 |
776 |
if (empty($i['ann']['env'])) { |
if (empty($i['ann']['env'])) { |
777 |
777 |
//rg_log($key . ': ' . $jid . ': conn has no environments.'); |
//rg_log($key . ': ' . $jid . ': conn has no environments.'); |
778 |
|
$reason .= 'E'; |
|
|
778 |
|
$reason[] = 'no env'; |
779 |
779 |
continue; |
continue; |
780 |
780 |
} |
} |
781 |
781 |
|
|
782 |
782 |
if (($i['worker_uid'] > 0) && ($i['worker_uid'] != $req['uid'])) { |
if (($i['worker_uid'] > 0) && ($i['worker_uid'] != $req['uid'])) { |
783 |
783 |
rg_log($key . ': ' . $jid . ': uids do not match, try next'); |
rg_log($key . ': ' . $jid . ': uids do not match, try next'); |
784 |
|
$reason .= 'U'; |
|
|
784 |
|
$reason[] = 'uids_mismatch'; |
785 |
785 |
continue; |
continue; |
786 |
786 |
} |
} |
787 |
787 |
|
|
|
... |
... |
function rg_process_job($db, &$job) |
790 |
790 |
if (!isset($workers_list[$k])) { |
if (!isset($workers_list[$k])) { |
791 |
791 |
rg_internal_error('Worker ' . $name . ' not found' |
rg_internal_error('Worker ' . $name . ' not found' |
792 |
792 |
. ' in workers_list! Strange!'); |
. ' in workers_list! Strange!'); |
793 |
|
$reason .= 'i'; |
|
|
793 |
|
$reason[] = 'worker_not_found'; |
794 |
794 |
continue; |
continue; |
795 |
795 |
} |
} |
796 |
796 |
$wi = $workers_list[$k]; |
$wi = $workers_list[$k]; |
797 |
797 |
|
|
798 |
798 |
if (isset($job['avoid'][$k]) && ($job['avoid'][$k] > time())) { |
if (isset($job['avoid'][$k]) && ($job['avoid'][$k] > time())) { |
799 |
799 |
rg_log($key . ': ' . $jid . ': we must avoid worker ' . $name); |
rg_log($key . ': ' . $jid . ': we must avoid worker ' . $name); |
800 |
|
$reason .= 'V'; |
|
|
800 |
|
$reason[] = 'avoid'; |
801 |
801 |
continue; |
continue; |
802 |
802 |
} |
} |
803 |
803 |
|
|
|
... |
... |
function rg_process_job($db, &$job) |
808 |
808 |
rg_log($key . ': ' . $jid . ': DEBUG: skip worker ' . $name . ' because' |
rg_log($key . ': ' . $jid . ': DEBUG: skip worker ' . $name . ' because' |
809 |
809 |
. ' sent jobs(' . $aj . ')' |
. ' sent jobs(' . $aj . ')' |
810 |
810 |
. ' >= workers(' . $wi['workers'] . ')'); |
. ' >= workers(' . $wi['workers'] . ')'); |
811 |
|
$reason .= 'O'; |
|
|
811 |
|
$reason[] = 'jobs/worker'; |
812 |
812 |
continue; |
continue; |
813 |
813 |
} |
} |
814 |
814 |
} |
} |
|
... |
... |
function rg_process_job($db, &$job) |
826 |
826 |
break; |
break; |
827 |
827 |
} |
} |
828 |
828 |
if (!$env_found) { |
if (!$env_found) { |
829 |
|
$reason .= 'e'; |
|
|
829 |
|
$reason[] = 'env_not_found'; |
830 |
830 |
continue; |
continue; |
831 |
831 |
} |
} |
832 |
832 |
|
|
|
... |
... |
function rg_process_job($db, &$job) |
859 |
859 |
|
|
860 |
860 |
// TODO: we should signal this and prevent the call if the list of |
// TODO: we should signal this and prevent the call if the list of |
861 |
861 |
// workers does not change. |
// workers does not change. |
862 |
|
rg_log('No workers found [' . $reason . ']! Suspend job for 10s'); |
|
|
862 |
|
rg_log('No workers found [' . implode(' ', $reason) . ']! Suspend job for 10s'); |
863 |
863 |
$job['next_try'] = time() + 10; |
$job['next_try'] = time() + 10; |
864 |
864 |
return TRUE; |
return TRUE; |
865 |
865 |
} |
} |
File scripts/worker.php changed (mode: 100644) (index b29604e..b46c6c3) |
... |
... |
function start_worker_build_tools($job, &$reason, &$reason2) |
497 |
497 |
. "\n" |
. "\n" |
498 |
498 |
. 'function rg_cp()' . "\n" |
. 'function rg_cp()' . "\n" |
499 |
499 |
. '{' . "\n" |
. '{' . "\n" |
500 |
|
. ' rg_op_s cp "${@}"' . "\n" |
|
|
500 |
|
. ' rg_op_s cp "${@}"' . "\n" //. ' rg_op_s strace -s2000 -f -q -tt -o /tmp/cp-${USER}.strace cp "${@}"' . "\n" |
501 |
501 |
. ' return ${E}' . "\n" |
. ' return ${E}' . "\n" |
502 |
502 |
. '}' . "\n" |
. '}' . "\n" |
503 |
503 |
. "\n" |
. "\n" |
|
... |
... |
function start_worker_build_tools($job, &$reason, &$reason2) |
752 |
752 |
. "\n" |
. "\n" |
753 |
753 |
. ' local dst_tar_gz="/mnt/rpmbuild/SOURCES/${pkg_name}-${pkg_ver}.tar.gz"' . "\n" |
. ' local dst_tar_gz="/mnt/rpmbuild/SOURCES/${pkg_name}-${pkg_ver}.tar.gz"' . "\n" |
754 |
754 |
. ' local dst_spec="/mnt/rpmbuild/SPECS/${spec_file_base}"' . "\n" |
. ' local dst_spec="/mnt/rpmbuild/SPECS/${spec_file_base}"' . "\n" |
755 |
|
. ' local rg_log N "DEBUG: dst_spec=${dst_spec}."' . "\n" |
|
|
755 |
|
. ' rg_log N "DEBUG: dst_spec=${dst_spec}."' . "\n" |
756 |
756 |
. "\n" |
. "\n" |
757 |
757 |
. ' rg_log N "Creating tar archive [${dst_tar_gz}]"' . "\n" |
. ' rg_log N "Creating tar archive [${dst_tar_gz}]"' . "\n" |
758 |
758 |
. ' rg_log N "Creating tar"' . "\n" |
. ' rg_log N "Creating tar"' . "\n" |
|
... |
... |
function start_worker_build_repo($job, $conf, &$reason, &$reason2) |
1034 |
1034 |
// Save gpg keys |
// Save gpg keys |
1035 |
1035 |
$keys = 0; |
$keys = 0; |
1036 |
1036 |
foreach ($job['pkg_repos'] as $pkg_repo_id => $info) { |
foreach ($job['pkg_repos'] as $pkg_repo_id => $info) { |
1037 |
|
if ($info['uid'] != $job['uid']) { |
|
|
1037 |
|
if (($job['uid'] != 0) && ($info['uid'] != $job['uid'])) { |
1038 |
1038 |
rg_log($job['id'] . ': DEBUG: skip storing key for' |
rg_log($job['id'] . ': DEBUG: skip storing key for' |
1039 |
1039 |
. ' pkg_repo_id ' . $pkg_repo_id |
. ' pkg_repo_id ' . $pkg_repo_id |
1040 |
|
. ' because the uids do not match'); |
|
|
1040 |
|
. ' because the uids do not match: ' |
|
1041 |
|
. ' info[uid]=' . $info['uid'] |
|
1042 |
|
. ' job[uid]=' . $job['uid']); |
1041 |
1043 |
continue; |
continue; |
1042 |
1044 |
} |
} |
1043 |
1045 |
|
|
|
... |
... |
function start_worker_build_repo($job, $conf, &$reason, &$reason2) |
1357 |
1359 |
. ' fi' . "\n" |
. ' fi' . "\n" |
1358 |
1360 |
. ' if [ "${job_uid}" = "${pkg_repo_uid}" ]; then' . "\n" |
. ' if [ "${job_uid}" = "${pkg_repo_uid}" ]; then' . "\n" |
1359 |
1361 |
. ' rg_op_s mkdir -p "${rgfs}" || break' . "\n" |
. ' rg_op_s mkdir -p "${rgfs}" || break' . "\n" |
1360 |
|
. ' rg_cp -av "${rpms_dir}"/*.rpm "${rgfs}/" || break' . "\n" |
|
|
1362 |
|
. ' rg_cp --force --verbose "${rpms_dir}"/*.rpm "${rgfs}/" || break' . "\n" |
1361 |
1363 |
. ' else' . "\n" // TODO: shouldn't I copy directly to ${rgfs}/${repo_username} if do_sensitive_ops==1? Seems it cannot happen! when we are uid 0, we do not need to copy! |
. ' else' . "\n" // TODO: shouldn't I copy directly to ${rgfs}/${repo_username} if do_sensitive_ops==1? Seems it cannot happen! when we are uid 0, we do not need to copy! |
1362 |
1364 |
. ' # "+" is used because it is not allowed in username' . "\n" |
. ' # "+" is used because it is not allowed in username' . "\n" |
1363 |
1365 |
. ' rg_op_s mkdir -p "${rgfs}/+pending/${repo_username}" || break' . "\n" |
. ' rg_op_s mkdir -p "${rgfs}/+pending/${repo_username}" || break' . "\n" |
1364 |
|
. ' rg_cp -av "${rpms_dir}/${repo_username}"/*.rpm "${rgfs}/+pending/${repo_username}/" || break' . "\n" |
|
|
1366 |
|
. ' rg_cp -v "${rpms_dir}/${repo_username}"/*.rpm "${rgfs}/+pending/${repo_username}/" || break' . "\n" |
1365 |
1367 |
. ' fi' . "\n" |
. ' fi' . "\n" |
1366 |
1368 |
. "\n" |
. "\n" |
1367 |
1369 |
. ' if [ "$(do_sensitive_ops)" != "1" ]; then' . "\n" |
. ' if [ "$(do_sensitive_ops)" != "1" ]; then' . "\n" |
|
... |
... |
function start_worker_build_repo($job, $conf, &$reason, &$reason2) |
1399 |
1401 |
. ' rg_log N "Copying files from ${debs_dir} to ${rgfs}"' . "\n" |
. ' rg_log N "Copying files from ${debs_dir} to ${rgfs}"' . "\n" |
1400 |
1402 |
. ' # "+" is used because it is not allowed in username' . "\n" |
. ' # "+" is used because it is not allowed in username' . "\n" |
1401 |
1403 |
. ' rg_op_s mkdir -p "${rgfs}/+pending/${job_id}" || break' . "\n" |
. ' rg_op_s mkdir -p "${rgfs}/+pending/${job_id}" || break' . "\n" |
1402 |
|
. ' rg_cp -av "${debs_dir}"/* "${rgfs}/+pending/${job_id}/" || break' . "\n" |
|
|
1404 |
|
. ' rg_cp -vR "${debs_dir}"/* "${rgfs}/+pending/${job_id}/" || break' . "\n" |
1403 |
1405 |
. ' if [ "$(do_sensitive_ops)" != "1" ]; then' . "\n" |
. ' if [ "$(do_sensitive_ops)" != "1" ]; then' . "\n" |
1404 |
1406 |
. ' rg_log N "Triggering the rebuild of subrepo"' . "\n" |
. ' rg_log N "Triggering the rebuild of subrepo"' . "\n" |
1405 |
1407 |
. ' echo "${pkg_subrepo_id}" >> /mnt/build2/pkg_subrepo_dirty' . "\n" |
. ' echo "${pkg_subrepo_id}" >> /mnt/build2/pkg_subrepo_dirty' . "\n" |
|
... |
... |
function xhandle_one($key, $data) |
2122 |
2124 |
if (!isset($jobs[$jid]['disk_size_gib'])) |
if (!isset($jobs[$jid]['disk_size_gib'])) |
2123 |
2125 |
$jobs[$jid]['disk_size_gib'] = '100'; |
$jobs[$jid]['disk_size_gib'] = '100'; |
2124 |
2126 |
if (!isset($jobs[$jid]['mem_mib'])) |
if (!isset($jobs[$jid]['mem_mib'])) |
2125 |
|
$jobs[$jid]['mem_mib'] = '2048'; |
|
|
2127 |
|
$jobs[$jid]['mem_mib'] = '4096'; |
2126 |
2128 |
if (!isset($jobs[$jid]['cpus'])) |
if (!isset($jobs[$jid]['cpus'])) |
2127 |
2129 |
$jobs[$jid]['cpus'] = '2'; |
$jobs[$jid]['cpus'] = '2'; |
2128 |
2130 |
$jobs[$jid]['state'] = RG_JOB_INIT; |
$jobs[$jid]['state'] = RG_JOB_INIT; |
File selinux/rocketgit.fc changed (mode: 100644) (index 2aaeda0..707c3a3) |
3 |
3 |
# MLS sensitivity: s0 |
# MLS sensitivity: s0 |
4 |
4 |
# MCS categories: <none> |
# MCS categories: <none> |
5 |
5 |
|
|
6 |
|
/etc/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_conf_t,s0) |
|
|
6 |
|
# '--' means ordinary file, '-d' directory etc. |
7 |
7 |
|
|
8 |
|
/var/log/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_log_t,s0) |
|
|
8 |
|
/etc/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_conf_t,s0) |
9 |
9 |
|
|
10 |
|
/var/lib/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_var_t,s0) |
|
11 |
|
/var/lib/rocketgit/locks(/.*)? gen_context(system_u:object_r:rocketgit_lock_t,s0) |
|
12 |
|
/var/lib/rocketgit/sockets(/.*)? gen_context(system_u:object_r:rocketgit_socket_t,s0) |
|
|
10 |
|
/var/log/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_log_t,s0) |
13 |
11 |
|
|
14 |
|
/usr/share/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_usr_t,s0) |
|
|
12 |
|
/var/lib/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_var_t,s0) |
|
13 |
|
/var/lib/rocketgit/locks(/.*)? gen_context(system_u:object_r:rocketgit_lock_t,s0) |
|
14 |
|
/var/lib/rocketgit/sockets(/.*)? gen_context(system_u:object_r:rocketgit_socket_t,s0) |
15 |
15 |
|
|
16 |
|
/usr/share/rocketgit/scripts/worker.(sh|php) gen_context(system_u:object_r:rocketgit_worker_exec_t,s0) |
|
17 |
|
/usr/share/rocketgit/scripts(/.*)? -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
|
18 |
|
/usr/share/rocketgit/hooks(/.*)? -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
|
|
16 |
|
/usr/share/rocketgit(/.*)? gen_context(system_u:object_r:rocketgit_usr_t,s0) |
19 |
17 |
|
|
20 |
|
/usr/lib/systemd/system/rocketgit-.*.service gen_context(system_u:object_r:rocketgit_unit_file_t,s0) |
|
|
18 |
|
/usr/share/rocketgit/scripts/worker.(sh|php) -- gen_context(system_u:object_r:rocketgit_worker_exec_t,s0) |
|
19 |
|
/usr/share/rocketgit/scripts(/.*)? -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
|
20 |
|
/usr/share/rocketgit/hooks(/.*)? -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
|
21 |
|
|
|
22 |
|
/usr/lib/systemd/system/rocketgit-.*.service -- gen_context(system_u:object_r:rocketgit_unit_file_t,s0) |
|
23 |
|
/usr/lib/systemd/system/rocketgit-.*.socket -- gen_context(system_u:object_r:rocketgit_unit_file_t,s0) |
|
24 |
|
|
|
25 |
|
/usr/sbin/rg_authorize -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
|
26 |
|
/usr/sbin/rg_change_pass -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
21 |
27 |
|
|
22 |
|
/usr/sbin/rg_authorize -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
|
23 |
|
/usr/sbin/rg_change_pass -- gen_context(system_u:object_r:rocketgit_exec_t,s0) |
|
File techdocs/payment.txt added (mode: 100644) (index 0000000..b2a3733) |
|
1 |
|
== How payment works? == |
|
2 |
|
|
|
3 |
|
User selects a plan at sign-up. He is redirect to the home page. |
|
4 |
|
When she hits the homepage, she is invited to select an amount |
|
5 |
|
(based on period: monthly or yearly). Then she press "Pay" button. |
|
6 |
|
We call 'pay_square_create_link' (passing an id which is payments.id) |
|
7 |
|
to create a payment link and we redirect the user to it. |
|
8 |
|
Sample link: https://sandbox.square.link/u/IgOz82xk |
|
9 |
|
The rg id, uid, operator name, 'plan' type and 'y' interval, 'init' |
|
10 |
|
state are inserted by calling 'pay_insert' function. |
|
11 |
|
pay_needed_high_level |
|
12 |
|
pay_square_create_link |
|
13 |
|
pay_insert |
|
14 |
|
We receive an order_id. |
|
15 |
|
|
|
16 |
|
Next step is to go to the external payment page. |
|
17 |
|
Payment takes place. |
|
18 |
|
External site redirects back to RocketGit (passing back the payment id). |
|
19 |
|
https://rg.embedromix.ro:9003/user/price1?paid=e09964ef29b3d886 |
|
20 |
|
|
|
21 |
|
Now, we received the payment id and we thank the user for the purchase. |
|
22 |
|
We need to schedule the checking of the payment, as an event, to be able |
|
23 |
|
to confirm it and mark it as paid. Should we? I think yes, because only now |
|
24 |
|
the user confirmed the payment. Yes, but what if we cannot update the db? |
|
25 |
|
Isn't it better to just check all initiated payments? I think yes. |
|
26 |
|
We connect to the payment provider and we will check the state of the payment. |
|
27 |
|
We also need to be able to compute the last paid day, to not bother the user |
|
28 |
|
earlier than needed. |
|
29 |
|
How should I compute it? And where to store this info? |
|
30 |
|
- case 1, user is paying immediately after sign-up (2023-02-10), pays for 1 month |
|
31 |
|
first day not paid is after exactly 1 month (2023-03-10) |
|
32 |
|
- case 2, user is paying after some days after sign-up (2023-02-10), pays for 1 month |
|
33 |
|
first day not paid is after exactly 1 month (2023-03-10) |
|
34 |
|
- what happens if we suspend the account for not paying? |
|
35 |
|
we still have resources used. Ask user to pay before unlocking resources? |
|
36 |
|
|
|
37 |
|
TODO: |
|
38 |
|
- We need to show correctly 12999 euro as 12.99 euro. |
|
39 |
|
1299/12990/USD 1/10/RON -> 1299=12.99/12990=129.90/USD 99=0.99/999=9.99/RON |
|
40 |
|
- What if the user does not pay and does not return to rg? We should |
|
41 |
|
reuse a previous payment if amount/period/plan match. |
|
42 |
|
- What if the user changes the plan on-th-fly? |
|
43 |
|
We need to think to multiple scenarios (cheaper plan or a more expensive one). |
|
44 |
|
- Should we offer one (last?) month free? |
|
45 |
|
- |