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.
How it works
Section titled “How it works”- The visitor opens the page and fills in the form: name, address, phone, email, currency and time zone.
- The page checks that the required fields are filled in and that the currency and time zone are from its lists.
- 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. - The page calls
sendEMailto send the credentials to the visitor’s email address, and shows a confirmation.
Before you start
Section titled “Before you start”- 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).getDictionarylists 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.
Configuration file
Section titled “Configuration file”Keep the API credentials in a file outside the web root, so that the web server never serves it:
<?phpdefine('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');The page
Section titled “The page”<?phprequire '/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 = <<<TEXTWelcome 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>Adapt the example
Section titled “Adapt the example”- Replace the IDs marked
/* your … */with the IDs of your service plan, routing group, media relay type and password policy. - Fill
$tzswith the time zones you offer, keyed byi_time_zone, and$currencieswith the currencies of your service plans. See Time zones and Supported currencies. - Change
balanceandcredit_limitonly if new accounts get free credit. With0.0they can make only free calls until they pay. - Edit the text of the welcome email and the brand name in it.
Related
Section titled “Related”- Create an account: every
createAccountparameter - Accounts generator: the
${N:…},${P:…}and${C:…}patterns - Send an email
- API overview: authentication and faults
- Accounts