Перейти до вмісту

Sign-up page example

Цей контент ще не доступний вашою мовою.

This example is a self-registration page for your website. A visitor fills in a form, and the page creates an account through the XML-RPC API and emails the new credentials to the visitor. It is one PHP file that runs on your own web server; the API is called from PHP on the server, never from the visitor’s browser.

  1. The visitor opens the page and fills in the form: name, address, phone, email, currency and time zone.
  2. The page checks that the required fields are filled in and that the currency and time zone are from its lists.
  3. The page calls createAccount. Patterns of the accounts generator such as ${N:[8][8][8][0-9][0-9][0-9][0-9]} and ${P:8} let the switch generate the login, the passwords and the voicemail PIN; the response returns the generated values.
  4. The page calls sendEMail to send the credentials to the visitor’s email address, and shows a confirmation.
  • Create a customer for the sign-up page, for example a reseller named web-signup, and enable API access for it as described in Enable API access. New accounts belong to this customer.
  • Note the IDs the new accounts need: the service plan (i_billing_plan), the routing group (i_routing_group), the media relay type (i_media_relay_type) and the password policy (i_password_policy). getDictionary lists the time zones, media relay types and other dictionaries.
  • Use PHP 8 or later and install the phpxmlrpc library on the web server. The example uses its classic API from xmlrpc.inc (xmlrpcval, xmlrpcmsg, xmlrpc_client), the same library the panel uses.

Keep the API credentials in a file outside the web root, so that the web server never serves it:

/etc/signup/signup-config.php
<?php
define('API_URL', 'https://panel.example.com/xmlapi/xmlapi');
define('API_LOGIN', 'web-signup');
define('API_PASSWORD', 'API-PASSWORD');
define('SIP_PROXY', 'sip.example.com');
define('MAIL_FROM', 'signup@example.com');
signup.php
<?php
require '/etc/signup/signup-config.php';
require 'xmlrpc/xmlrpc.inc'; /* phpxmlrpc library */
$currencies = ['USD' => 'USD', 'EUR' => 'EUR' /* ... and so on */];
$tzs = [ /* i_time_zone => name */
'97' => 'Africa/Abidjan',
'145' => 'Africa/Accra',
'140' => 'Europe/London',
/* ... and so on */
];
function par($name) {
return isset($_POST[$name]) ? trim((string) $_POST[$name]) : '';
}
function h($s) {
return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
function api_call($method, array $params) {
$cli = new xmlrpc_client(API_URL);
$cli->request_charset_encoding = 'UTF-8';
$cli->return_type = 'phpvals';
$cli->setCredentials(API_LOGIN, API_PASSWORD, CURLAUTH_DIGEST);
$cli->setSSLVerifyPeer(true);
$cli->setSSLVerifyHost(2);
/* for a certificate of your own CA: $cli->setCaCertificate('/etc/signup/ca.pem'); */
$r = $cli->send(new xmlrpcmsg($method, [new xmlrpcval($params, 'struct')]), 20);
if ($r->faultCode()) {
error_log("$method: fault " . $r->faultCode() . ': ' . $r->faultString());
return false;
}
return $r->value();
}
function createAccount() {
$p = [
'username' => new xmlrpcval('${N:[8][8][8][0-9][0-9][0-9][0-9]}', 'string'),
'web_password' => new xmlrpcval('${P:8}', 'string'),
'authname' => new xmlrpcval('${C:username}', 'string'),
'voip_password' => new xmlrpcval('${P:7}', 'string'),
'i_billing_plan' => new xmlrpcval(11, 'int'), /* your service plan */
'i_media_relay_type' => new xmlrpcval(0, 'int'), /* your media relay type */
'i_password_policy' => new xmlrpcval(1, 'int'), /* your password policy */
'i_routing_group' => new xmlrpcval(10, 'int'), /* your routing group */
'i_time_zone' => new xmlrpcval((int) par('i_time_zone'), 'int'),
'i_lang' => new xmlrpcval('en', 'string'),
'balance' => new xmlrpcval(0.0, 'double'),
'credit_limit' => new xmlrpcval(0.0, 'double'),
'blocked' => new xmlrpcval(0, 'int'),
'max_sessions' => new xmlrpcval(-1, 'int'), /* unlimited */
'max_credit_time' => new xmlrpcval(3600, 'int'),
'translation_rule' => new xmlrpcval('', 'string'),
'cli_translation_rule' => new xmlrpcval('', 'string'),
'cpe_number' => new xmlrpcval('', 'string'),
'i_export_type' => new xmlrpcval(2, 'int'),
'reg_allowed' => new xmlrpcval(1, 'int'),
'trust_cli' => new xmlrpcval(0, 'int'),
'disallow_loops' => new xmlrpcval(0, 'int'),
'vm_password' => new xmlrpcval('${N:[0-9][0-9][0-9][0-9][0-9][0-9]}', 'string'),
'vm_enabled' => new xmlrpcval(1, 'int'),
'vm_notify_emails' => new xmlrpcval(par('vm_notify_emails'), 'string'),
'vm_forward_emails' => new xmlrpcval(par('vm_forward_emails'), 'string'),
'vm_del_after_fwd' => new xmlrpcval(0, 'int'),
'mid_init' => new xmlrpcval('', 'string'),
'contact' => new xmlrpcval('', 'string'),
'alt_contact' => new xmlrpcval('', 'string'),
'payment_currency' => new xmlrpcval(par('payment_currency'), 'string'),
'payment_method' => new xmlrpcval(1, 'int'),
'on_payment_action' => new xmlrpcval(null, 'null'), /* No Action */
'min_payment_amount' => new xmlrpcval(0.0, 'double'),
'lifetime' => new xmlrpcval(-1, 'int'), /* unlimited */
'preferred_codec' => new xmlrpcval(18, 'int'), /* G.729 */
'use_preferred_codec_only' => new xmlrpcval(0, 'int'),
'welcome_call_ivr' => new xmlrpcval(null, 'null'), /* System Default */
];
foreach (['company_name', 'salutation', 'first_name', 'last_name', 'street_addr',
'state', 'postal_code', 'city', 'country', 'phone', 'fax', 'alt_phone',
'email', 'cc', 'bcc'] as $f) {
$p[$f] = new xmlrpcval(par($f), 'string');
}
return api_call('createAccount', $p);
}
function sendWelcome(array $a) {
$proxy = SIP_PROXY;
$body = <<<TEXT
Welcome to Example Telecom!
Please keep this email for your records. Your account information:
SIP login: {$a['authname']}
SIP password: {$a['voip_password']}
Web login: {$a['username']}
Web password: {$a['web_password']}
SIP proxy: {$proxy}
When you log in for the first time, you are asked to change your web password.
To make paid calls, top up your balance online.
Thank you for registering!
TEXT;
api_call('sendEMail', [
'from' => new xmlrpcval(MAIL_FROM, 'string'),
'to' => new xmlrpcval(par('email'), 'string'),
'cc' => new xmlrpcval('', 'string'),
'bcc' => new xmlrpcval('', 'string'),
'subject' => new xmlrpcval('Sign-up confirmation', 'string'),
'body' => new xmlrpcval($body, 'string'),
]);
}
$required = ['first_name', 'last_name', 'street_addr', 'state', 'postal_code',
'city', 'country', 'phone', 'email', 'payment_currency', 'i_time_zone'];
$submitted = $_SERVER['REQUEST_METHOD'] === 'POST';
$ok = true;
$created = false;
if ($submitted) {
foreach ($required as $f) {
if (par($f) === '') {
$ok = false;
}
}
if (!filter_var(par('email'), FILTER_VALIDATE_EMAIL)
|| !isset($currencies[par('payment_currency')])
|| !isset($tzs[par('i_time_zone')])
|| par('terms') !== 'yes') {
$ok = false;
}
if ($ok) {
$a = createAccount();
if ($a) {
sendWelcome($a);
$created = true;
} else {
$ok = false;
}
}
}
$fields = [ /* name => [label, required] */
'company_name' => ['Company Name', false], 'salutation' => ['Mr./Ms...', false],
'first_name' => ['First Name', true], 'last_name' => ['Last Name', true],
'street_addr' => ['Address', true], 'state' => ['State', true],
'postal_code' => ['Postal Code', true], 'city' => ['City', true],
'country' => ['Country', true], 'phone' => ['Phone', true],
'fax' => ['Fax', false], 'alt_phone' => ['Alt. Phone', false],
'email' => ['Email', true], 'cc' => ['CC', false],
'bcc' => ['BCC', false],
'vm_forward_emails' => ['Voicemail forwarding email', false],
'vm_notify_emails' => ['Voicemail notification email', false],
];
$cur_sel = $submitted ? par('payment_currency') : 'USD';
$tz_sel = $submitted ? par('i_time_zone') : '140'; /* Europe/London */
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sign up</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 40rem; margin: 2rem auto; padding: 0 1rem; }
label { display: block; margin-top: .75rem; }
input, select { width: 100%; padding: .4rem; box-sizing: border-box; }
input[type=checkbox] { width: auto; }
.error { color: #b00020; }
</style>
</head>
<body>
<h1>Sign up</h1>
<?php if ($created) { ?>
<p>Thank you for registering. Your credentials have been sent to <?= h(par('email')) ?>.</p>
<?php } else { ?>
<?php if (!$ok) { ?>
<p class="error">Please fill in all required fields correctly and accept the terms.</p>
<?php } ?>
<form method="post">
<?php foreach ($fields as $name => [$label, $req]) { ?>
<label><?= $req ? '<b>' . h($label) . '</b>' : h($label) ?>
<input name="<?= $name ?>" type="<?= $name === 'email' ? 'email' : 'text' ?>"
value="<?= h(par($name)) ?>"<?= $req ? ' required' : '' ?>>
</label>
<?php } ?>
<label><b>Currency</b>
<select name="payment_currency">
<?php foreach ($currencies as $k => $v) { ?>
<option value="<?= h($k) ?>"<?= $cur_sel === $k ? ' selected' : '' ?>><?= h($v) ?></option>
<?php } ?>
</select>
</label>
<label><b>Time zone</b>
<select name="i_time_zone">
<?php foreach ($tzs as $k => $v) { ?>
<option value="<?= h($k) ?>"<?= $tz_sel === (string) $k ? ' selected' : '' ?>><?= h($v) ?></option>
<?php } ?>
</select>
</label>
<label><input type="checkbox" name="terms" value="yes" required>
I have read and agree to the Terms and Conditions</label>
<p><button type="submit">Sign up</button></p>
</form>
<?php } ?>
</body>
</html>
  • Replace the IDs marked /* your … */ with the IDs of your service plan, routing group, media relay type and password policy.
  • Fill $tzs with the time zones you offer, keyed by i_time_zone, and $currencies with the currencies of your service plans. See Time zones and Supported currencies.
  • Change balance and credit_limit only if new accounts get free credit. With 0.0 they can make only free calls until they pay.
  • Edit the text of the welcome email and the brand name in it.