Monday, April 3, 2017

Per User PIN for FreePBX 2.x

This article shows how to very easily add a per-user pin for outbound calls using FreePBX systems. Sometimes trunk level isn’t too fun. Also, if you don’t want to use a specially created  DB, you can use FreePBX’s pin module and “Refer” to that PIN when verifying. That’s something i am not covering here.

Steps

1) Create Database/Tables

2) Insert dialplan

3) Create users in table

READ THIS NOW

  • In the dialplan be sure to change sqluser and sqlpass to your MySQL user and password allowed to at minimum do a SELECT to the above DB/table
  • These dialplans uses the default sound files from Asterisk distribution, change were you see fit, where the  “Playback” and “Read”  app uses as below
  • Iteration for wrong pin is 3 times
  • PIN length is 4 digits, change if you need larger, the size of the int(4) in DB to int(6) for example, then at the dialplan change 5 in the readpin line
  • Hang up if wrong pin
  • If pin defined, will use usual routes set, if route has a pin, user has to key in twice
  • Valid and Invalid pin attempts  are stored in CDR as accountcode
  • ISSUE: Billing seconds in Asterisk is counted when this app executed. If you do billing, this might be a problem, otherwise, don’t bother

 

Create Database/Tables

Simply run this sql query and it will add the necessary table/data. If not, here’s the schema below that.

--WARNING, THIS WILL DROP EXISTING DB/TABLE

DROP DATABASE IF EXISTS `custom_pin`;
CREATE DATABASE `custom_pin` /*!40100 DEFAULT CHARACTER SET latin1 */;
USE `custom_pin`;

DROP TABLE IF EXISTS `tbl_custom_pins`;
CREATE TABLE `tbl_custom_pins` (
  `user` int(4) NOT NULL,
  `pin` int(8) NOT NULL,
  `comment` varchar(200) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
 

Create a database called “custom_pin”, inside this DB, create a table called tbl_custom_pins

Add entries like below.

image

 

Insert dialplan

- Edit /etc/asterisk/extensions_custom.conf

- If you do not already or use macro [macro-dialout-trunk-predial-hook], create one like this, and add the following lines

[macro-dialout-trunk-predial-hook]

exten => s,1,Macro(custom-pins)

 

Now, we create the macro, custom-pins, copy paste the lines below

;; CUSTOM PIN START COPY HERE
[macro-custom-pins]
exten => s,1,NoOp(CUSTOM PIN MODULE - USE DATABASE TO DEFINE)
exten => s,n,Wait(1)
exten => s,n,Macro(app-custom-pin,s,1)
exten => s,n,MacroExit()

[macro-app-custom-pin]
exten => s,1,NoOp(CHECKING IF PIN ENABLED AND VERIFYING IF IT IS)
exten => s,n,Set(PINCOUNT=0)
exten => s,n,Set(ALLOWERROR=0)
exten => s,n,Gotoif($["${AMPUSER}"=""]?skip) ;;if not ampuser skip

exten => s,n,MYSQL(Connect connid localhost sqluser sqlpass  custom_pin)
exten => s,n,MYSQL(Query resultid ${connid} SELECT pin from tbl_custom_pins where user='${AMPUSER}' LIMIT 1)
exten => s,n,MYSQL(Fetch fetchid ${resultid} DBPIN)
exten => s,n,NoOp(DB Results spits out ${DBPIN} or ${VAR1})
exten => s,n,MYSQL(Clear ${resultid})
exten => s,n,MYSQL(Disconnect ${connid})
exten => s,n,GotoIf($["${DBPIN}"=""]?skip:readpin)

exten => s,n(readpin),Read(PIN,en/pin_number,,,1,5)
exten => s,n,Gotoif($["${PIN}"="${DBPIN}"]?pass)
exten => s,n,Playback(custom/invalid)
exten => s,n,Set(PINCOUNT=$[${PINCOUNT}+1])
exten => s,n,GotoIf($[${PINCOUNT}>2]?toomanyerros)
exten => s,n,Goto(readpin)

exten => s,n(skip),NoOp(NO PIN DEFINED)
exten => s,n,MacroExit()

exten => s,n(pass),NoOp(PIN IS OK)
exten => s,n,Playback(auth-thankyou)
exten => s,n,Set(CDR(accountcode)=${DBPIN})
exten => s,n,MacroExit()

exten => s,n(toomanyerros),Playback(en/an-error-has-occured)
exten => s,n,Playback(terminating)
exten => s,n,Set(CDR(accountcode)=PIN-ERR)
exten => s,n,Hangup(16)

;; END COPY HERE

Create Users

The app uses the variable {AMPUSER} which almost all the time is declared by FreePBX, it will not work if that’s missing! Meaning this could be from users detached from a device in device user mode. If {AMPUSER} is not found or not defined/zero value, the dialplan will also skip, allowing users to call out as usual. If defined, it will be checked against this {AMPUSER} variable and if match, it will ask for PIN, if there’s no DB match, it will proceed allowing users to call out like usual.

Remember, the user part in DB is the user defined as “User” in device user mode, but if its in (default) extensions mode, it will always be the same, meaning SIP/1000 will always be user 1000 as well.