Additional modules for fraud protection

From ISPWiki

Jump to: navigation, search

BILLmanager allows you to add custom module handlers. The fraud system module structure contains two files:

  1. The XML file that describes the interface called billmgr_mod_xxx.xml, (where xxx is random symbol) that is used how to set up connection parameters. The file should locate in the {path to installation folder}/etc/ directory and should be encoded in the UTF-8 character set.
  2. The binary or test file (depending the language) of a module handler. The file should locate in the /usr/local/ispmgr/sbin/ directory, and its name should start with fp.

Contents

XML file structure

An XML consists of two parts:

  • Description of the parameter form
  • Localized fields
<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
	<metadata name="fraudparam_xxx" type="form"> <!-- xxx - имя вашего модуля без '''fp''' -->
		<form>
			<!--Configuration fields required for your module, which are displayed when entering parameters of the module-->
			<field name="field_name_1">
				<input type="text" name="field_name_1"/>
			</field>
			<!--...-->
			<field name="field_name_n">
				<input type="text" name="field_name_n"/>
			</field>
		</form>
	</metadata>

	<metadata name="smsgateparam_xxx" type="form"> <!-- xxx - name of your module without '''fp'''. This module is required if you are going to use it as an SMS gateway -->
		<form>
			<!--Configuration fields required for your module, which are displayed when entering parameters of the module-->
			<field name="field_name_1">
				<input type="text" name="field_name_1"/>
			</field>
			<!--...-->
			<field name="field_name_n">
				<input type="text" name="field_name_n"/>
			</field>
		</form>
	</metadata>

	<lang name="en"> <!-- Several languages must the described in an XML document. The English language is obligatory -->
		<messages name="fraudconf">
			<msg name="xxx">XXX</msg> <!-- xxx - name of your module without '''fp''', XXX - name of the module on the list -->
		</messages>

		<messages name="fraudparam_xxx"> <!-- xxx - name of your module without '''fp''' -->
			<msg name="title">Title</msg> <!-- title of the input box -->
			<msg name="field_name_1">field name 1</msg> <!-- name of module settings' field -->
			<msg name="hint_field_name_1">hint field name 1</msg> <!-- hint that is displayed when moving the mouse cursor over the field' name -->
			<!--...-->
			<msg name="field_name_n">field name n</msg>
			<msg name="hint_field_name_n">hint field name n</msg>
		</messages>
		<messages name="smsgateparam_xxx"> <!-- xxx - name of your module without '''fp'''. This module is required if you are going to use it as an SMS gateway -->
			<msg name="title">Title</msg> <!-- title of the input box -->
			<msg name="field_name_1">field name 1</msg> <!-- name of module settings' field -->
			<msg name="hint_field_name_1">hint field name 1</msg> <!-- hint that is displayed when moving the mouse cursor over the field' name -->
			<!--...-->
			<msg name="field_name_n">field name n</msg>
			<msg name="hint_field_name_n">hint field name n</msg>
		</messages>
	</lang>

	<lang name="ru">
		<!--The same parameters for another language-->
	</lang>
</mgrdata>

Module structure

BILLmanager passes the data to a module file via the command line parameters.

The handler module must process the command line parameters and respond to the commands.

The module configuration parameters are located in the '{path to installation folder}/etc/fpxxx.conf (sgxxx{partner ID}.conf - to set up an SMS gateway), where xxx is a module name in the format: <parameter name> <value>. Each parameter is specified in a separate line.

Received parameters and commands

  • features - a list of supported features should be passed to STDIN: fraud and/orgate, for example: "fraud gate".
  • validate - check the data and pass 'ok' to STDOUT.
  • tune - if necessary, pass the XML document describing the interface to STDOUT.
  • type - pass a module type: 'sms', if an SMS is to be sent, or 'call', if a call is to be made.
  • call - call the handler to send an SMS or make a call. The full version looks like this 'fpxxx call ccode phone code lang', where call is a master command, ccode is a country code in the phone number (the first line received when verifying a phone number), phone is a phone number, code is a verification code, lang is a default user language.
  • sendsms - the command to pass an SMS; possible parameters: partnerid' phone' and a message text, where 'partnerid' is a partner account's identifier, if an sms is sent to a partner's client; 'phone' is a phone number to which the sms should be sent.
  • If completed successfully, call the command '{path to installation folder}/sbin/mgrctl -m billmgr -o xml longtask.finish elid=(PID of startup file) status=ok'. Once the sms has been successfully sent, pass "OK" to STDOUT, otherwise send "ERROR".
  • If not, call the command '{path to installation folder}/sbin/mgrctl -m billmgr -o xml longtask.finish elid=(PID of the startup file) status=err errmsg=(text of the error message)'

More information can be found in the article LongTask

Example

Consider creating a module script for connecting to API TextMagic (the XML text given below is only an example, you must replace it with valid parameters).

XML document

The XML document:

<?xml version="1.0" encoding="UTF-8"?>
<mgrdata>
	<metadata name="fraudparam_textmagic" type="form">
		<form>

Following are the module configuration parameters: <field name="username">

				<input type="text" name="username" empty="no"/>
			</field>
			<field name="password">
				<input type="text" name="password" empty="no"/>
			</field>
			<field name="phonereg">
				<input type="text" name="phonereg"/>
			</field>
		</form>
	</metadata>
	<metadata name="smsgateparam_textmagic" type="form">
		<form>

Following are the sms gateway configuration parameters:

			<field name="username">
				<input type="text" name="username" empty="no"/>
			</field>
			<field name="password">
				<input type="text" name="password" empty="no"/>
			</field>
		</form>
	</metadata>

Example in English:

	<lang name="en">
		<messages name="fraudconf">
			<msg name="textmagic">Text Magic</msg>
		</messages>

		<messages name="fraudparam_textmagic">
			<msg name="title">Phone check from Text Magic</msg>
			<msg name="username">User name</msg>
			<msg name="hint_username">Specify a user name</msg>
			<msg name="password">Password</msg>
			<msg name="hint_password">Specify a password</msg>
			<msg name="phonereg">Phone filter</msg>
			<msg name="hint_phonereg">Specify a phone filter. This field can be empty.</msg>
		</messages>
		<messages name="smsgateparam_textmagic">
			<msg name="title">SMS gate from Text Magic</msg>
			<msg name="username">User name</msg>
			<msg name="hint_username">Specify a user name</msg>
			<msg name="password">Password</msg>
			<msg name="hint_password">Specify a password</msg>
		</messages>
	</lang>

Example in Russian:

	<lang name="ru">
		<messages name="fraudconf">
			<msg name="textmagic">Text Magic</msg>
		</messages>

		<messages name="fraudparam_textmagic">
			<msg name="title">Проверка телефона от Text Magic</msg>
			<msg name="username">Имя пользователя</msg>
			<msg name="hint_username">Укажите имя пользователя</msg>
			<msg name="password">Пароль</msg>
			<msg name="hint_password">Укажите пароль</msg>
			<msg name="phonereg">Фильтр номеров</msg>
			<msg name="hint_phonereg">Укажите фильтр разрешенных номеров телефонов. Поле можно оставить пустым</msg>
		</messages>
		<messages name="smsgateparam_textmagic">
			<msg name="title">СМС шлюз от Text Magic</msg>
			<msg name="username">Имя пользователя</msg>
			<msg name="hint_username">Укажите имя пользователя</msg>
			<msg name="password">Пароль</msg>
			<msg name="hint_password">Укажите пароль</msg>
		</messages>
	</lang>
</mgrdata>

Script handler

Script handler written in PHP

#!/usr/bin/php
<?php

Set your error handler for logging errors instead of passing them to STDOUT:

	set_error_handler("tmErrorHandler");

Open the log file:

	$log_file = fopen("/usr/local/ispmgr/var/fptextmagic.log", "a");
	fwrite($log_file, "=======".date("M j H:i:s") . "[] " ."=======\n");

Enter the parameters into the log file:

	foreach($argv as $line_num => $line) {
		fwrite($log_file, date("M j H:i:s") . "[] " . $line_num.":".$line."\n");
	}

Process the received parameters (the first parameter is a startup file), if the number of received parameters is less than 2, you need to output the information concerning the module usage. 3 or 4 parameters are passed for the 'call' command, thus the module must receive 4 or 5 parameters.

	if ($argc<2) {
		usage();
	} else {
		switch($argv[1]) {

Output 'ok':

			case "features":
				echo "fraud gate";
				break;
			case "validate":
				echo "ok";
				break;
			case "tune":

Output the module type sms:

			case "type":
				echo "sms";
				break;

Call the handler for sending SMS:

			case "call":
				if ($argc<5 || $argc>6) {
					fwrite($log_file, date("M j H:i:s") . "[] " . "Invalid params number." . "\n");

					usage();
				} else {
					fwrite($log_file, date("M j H:i:s") . "[] " . "Start call API." . "\n");

					if ($argc == 4) {
						callfraud($argv[2] . $argv[3], $argv[4]);
					} else {
						callfraud($argv[2] . $argv[3], $argv[4], $argv[5]);
					}
				}
				break;
			case "sendsms":
				if ($argc != 3) {
					fwrite($log_file, date("M j H:i:s") . "[] " . "Invalid params number." . "\n");

					usage();
				} else {
					fwrite($log_file, date("M j H:i:s") . "[] " . "Start call API." . "\n");
					$msg;
					$f = fopen('php://stdin', 'r');
					while ($line = fgets($f))
						$msg .= $line;
					callgate($argv[2], $argv[3], $msg);
				}
				break;
			default:
				usage();
		}	
	}

	fwrite($log_file, "=======".date("M j H:i:s") . "[] " ."=======\n");
	fclose($log_file);

The module usage output function:

	function usage() {
		print("ISPsystem BILLmanager plugin v1.0
Text Magic integration plugin.
Usage:
	features - print 'fraud gate';
	validate - print 'ok';
	tune - no return value;
	type - return 'sms' as type of plugin;
	sendsms 'partnerid' 'phone_number' <msg> - send sms to phone number;
	call 'country_code' 'phone_number' 'verification_code' 'lang' - execute plugin function.\n");
}

SMS processing function for fraud protection:

	function callfraud($phone, $code, $lang = "en") {
		global $log_file;

		fwrite($log_file, date("M j H:i:s") . "[] " . "Phone: " . $phone . " Code: " . $code . "\n");

		$msg = "Your verification code is ".$code;

Get parameters from the configuration file:

		$lines = file("/usr/local/ispmgr/etc/fptextmagic.conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

		$params = array();

		foreach ($lines as $line_num => $line) {
			$arr_key = "";
			$arr_val = "";
			list($arr_key, $arr_val) = explode(" ", $line, 2);
			$params += array($arr_key => $arr_val);
		}

		$curl_client = curl_init("https://www.textmagic.com/app/api");

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");;

Form the array to pass to the server.

		$data = array("username" => $params["username"], "password" => $params["password"], "cmd" => "send",
			      "text" => $msg, "phone" => $phone, "unicode" => "0");

		curl_setopt($curl_client, CURLOPT_SSL_VERIFYPEER, 0);

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		curl_setopt($curl_client, CURLOPT_POST, 1);

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		curl_setopt($curl_client, CURLOPT_POSTFIELDS, $data);

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		$output = curl_exec($curl_client); //В случае успешного завершения запроса в $output помещается 1, в противном случае ничего.

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		fwrite($log_file, date("M j H:i:s") . "[] " . $output . "\n");

Finish the module:

		fwrite($log_file, date("M j H:i:s") . "[] Finish task with PID file " . getenv("MGR_LT_PID") . "\n");

		if ($output == "1") {
			exec("/usr/local/ispmgr/sbin/mgrctl -m billmgr -o xml longtask.finish elid=". getenv("MGR_LT_PID") ." status=ok");
		} else {
			exec("/usr/local/ispmgr/sbin/mgrctl -m billmgr -o xml longtask.finish elid=". getenv("MGR_LT_PID") ." status=err errmsg='Error with cURL'");
		}

		curl_close($curl_client);
	}

SMS send function (as a gateway):

	function callgate($partnerid, $phone, $msg) {
		global $log_file;

		fwrite($log_file, date("M j H:i:s") . "[] " . "PartnerID: " . $partnerid . " Phone: " . $phone . "\n");

Get parameters from the configuration file:

		$lines = file("/usr/local/ispmgr/etc/sgtextmagic" . ($partnerid > 0 ? $partnerid : "") . ".conf", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

		$params = array();

		foreach ($lines as $line_num => $line) {
			$arr_key = "";
			$arr_val = "";
			list($arr_key, $arr_val) = explode(" ", $line, 2);
			$params += array($arr_key => $arr_val);
		}

		$curl_client = curl_init("https://www.textmagic.com/app/api");

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

Form the array to pass to the server:

		$data = array("username" => $params["username"], "password" => $params["password"], "cmd" => "send",
			      "text" => $msg, "phone" => $phone, "unicode" => "0");

		curl_setopt($curl_client, CURLOPT_SSL_VERIFYPEER, 0);

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		curl_setopt($curl_client, CURLOPT_POST, 1);

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		curl_setopt($curl_client, CURLOPT_POSTFIELDS, $data);

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		$output = curl_exec($curl_client); //В случае успешного завершения запроса в $output помещается 1, в противном случае ничего.

		fwrite($log_file, date("M j H:i:s") . "[] " . curl_error($curl_client) . "\n");

		fwrite($log_file, date("M j H:i:s") . "[] " . $output . "\n");

		curl_close($curl_client);
	}

Error handler function:

	function tmErrorHandler($errno, $errstr, $errfile, $errline) {
		global $log_file;
		fwrite($log_file, date("M j H:i:s") . "[] " . "Error [" . $errno . "] ErrMsg: " . $errstr . ". In file: " . $errfile . ". In line: " . $errline . "\n");
	    return true;
	}
?>

Script handler written in Python 2.6

Specify a script handler and import the required modules:

#! /usr/bin/env python
import sys, string, time, httplib, urllib, os, subprocess

Specify required functions


Define the output function into the log fie:

def log(msg):
	log_file.write(time.strftime("%b %d %H:%M:%S[] ") + msg + "\n")

Define the function to output the script usage information:

def usage():
	print "ISPsystem BILLmanager plugin v1.0"
	print "Text Magic integration plugin."
	print "Usage:"
	print "\tvalidate - print 'ok';"
	print "\ttune - no return value;"
	print "\ttype - return 'sms' as type of plugin;"
	print "\tcall 'country_code' 'phone_number' 'verification_code' 'lang' - execute plugin function.\n"

Define the function to send SMS:

def callapi(phone, code, lang="en"):
	log("Start call api: phone = " + phone + ", code = " + code + ", lang = " + lang)
	msg = "Your verification code is " + code

Open and read the configuration file:

	config = open("/usr/local/ispmgr/etc/fptextmagic.conf", "r")
	params = {}
	for line in config.readlines():
		line = string.strip(line, " \n")
		kv = line.split(" ")
		try:
			params[kv[0]] = kv[1]
		except IndexError:
			params[kv[0]] = ""
	config.close()

Form the array to send to the server. Use the object of the HTTPSConnection class to send the request:

	params = urllib.urlencode({'username': params["username"], 'password': params["password"], 'cmd': "send", "text": "Your verification code is " + code, 'phone': phone, 'unicode': "0"})
	headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
	http_client = httplib.HTTPSConnection("www.textmagic.com");
	http_client.request("POST", "/app/api", params, headers)
	response = http_client.getresponse()
	data = response.read()
	log(str(response.status) + ":" + str(data))

Finish the module. If the MGR_LT_PID environment variable is specified, inform BILLmanager about the script completion:

	if MGR_LT_PID == "None":
		log("Standalong. No finish action")
	else:
		if response.status == 200:
			subprocess.Popen(["/usr/local/ispmgr/sbin/mgrctl", "-m", "billmgr", "-o", "xml", "longtask.finish", "elid=" + str(os.getenv("MGR_LT_PID")), "status=ok"]);
		else:
			subprocess.Popen(["/usr/local/ispmgr/sbin/mgrctl", "-m", "billmgr", "-o", "xml", "longtask.finish", "elid=" + str(os.getenv("MGR_LT_PID")), "status=err", "errmsg='Error with cURL'"]);

Main script code


Open the log file to add messages:

log_file = open("/usr/local/ispmgr/var/fptextmagic.log", "a")

Redirect errors into the log file:

sys.stderr = log_file

Get the environment variable that contains the name of the PID-file of the longtask process.

MGR_LT_PID = str(os.getenv("MGR_LT_PID"))

Process the received command line parameters:

if len(sys.argv) < 2:
	log("Too few parameters, print usage")
	usage()
else:

Output to the validate command:

	if sys.argv[1] == "validate":
		print "ok"

Output to the tune command:

	elif sys.argv[1] == "tune":
		print ""

Output to the type command:

	elif sys.argv[1] == "type":
		print "sms"

Process the sms send command (get the parameters and run the send function):

	elif sys.argv[1] == "call":
		if len(sys.argv) < 5 or len(sys.argv) > 6:
			log("Too few or a lot parameters, print usage")
			usage()
		else:
			phone = sys.argv[2] + sys.argv[3]
			code = sys.argv[4]
			if len(sys.argv) == 5:
				callapi(phone, code)
			elif len(sys.argv) == 6:
				lang = sys.argv[5]
				callapi(phone, code, lang)
			else:
				log("Too few or a lot parameters, print usage")
				usage()
	else:
		usage()

Close the pointer to the log file:

log_file.close()
Was this helpful? Yes | No
Personal tools