mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
pulled the debit methods in the api interface
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
package main
|
||||
|
||||
import(
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/rif/cgrates/timespans"
|
||||
"log"
|
||||
"net/http"
|
||||
"encoding/json"
|
||||
"github.com/rif/cgrates/timespans"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type IncorrectParameters struct {
|
||||
@@ -30,20 +31,83 @@ func getCostHandler(w http.ResponseWriter, r *http.Request) {
|
||||
enc := json.NewEncoder(w)
|
||||
r.ParseForm()
|
||||
cstmid, ok1 := r.Form["cstmid"]
|
||||
subj, ok2 :=r.Form["subj"]
|
||||
subj, ok2 := r.Form["subj"]
|
||||
dest, ok3 := r.Form["dest"]
|
||||
if !ok1 || !ok2 || !ok3 {
|
||||
enc.Encode(IncorrectParameters{"Incorrect parameters"})
|
||||
return
|
||||
}
|
||||
arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]}
|
||||
callCost := CallRater(arg)
|
||||
callCost := GetCost(arg)
|
||||
enc.Encode(callCost)
|
||||
}
|
||||
|
||||
func listenToHttpRequests(){
|
||||
/*
|
||||
curl "http://127.0.0.1:8000/getcost?cstmid=vdf&subj=rif&dest=0257@amount=100"
|
||||
*/
|
||||
func debitBalanceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
enc := json.NewEncoder(w)
|
||||
r.ParseForm()
|
||||
cstmid, ok1 := r.Form["cstmid"]
|
||||
subj, ok2 := r.Form["subj"]
|
||||
dest, ok3 := r.Form["dest"]
|
||||
amount_s, ok4 := r.Form["amount"]
|
||||
amount, err := strconv.ParseFloat(amount_s[0], 64)
|
||||
if !ok1 || !ok2 || !ok3 || ok4 || err != nil {
|
||||
enc.Encode(IncorrectParameters{"Incorrect parameters"})
|
||||
return
|
||||
}
|
||||
arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
|
||||
result := Debit(arg, "Storage.DebitCents")
|
||||
enc.Encode(result)
|
||||
}
|
||||
|
||||
/*
|
||||
curl "http://127.0.0.1:8000/getcost?cstmid=vdf&subj=rif&dest=0257@amount=100"
|
||||
*/
|
||||
func debitSMSHandler(w http.ResponseWriter, r *http.Request) {
|
||||
enc := json.NewEncoder(w)
|
||||
r.ParseForm()
|
||||
cstmid, ok1 := r.Form["cstmid"]
|
||||
subj, ok2 := r.Form["subj"]
|
||||
dest, ok3 := r.Form["dest"]
|
||||
amount_s, ok4 := r.Form["amount"]
|
||||
amount, err := strconv.ParseFloat(amount_s[0], 64)
|
||||
if !ok1 || !ok2 || !ok3 || !ok4 || err != nil {
|
||||
enc.Encode(IncorrectParameters{"Incorrect parameters"})
|
||||
return
|
||||
}
|
||||
arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
|
||||
result := Debit(arg, "Storage.DebitSMS")
|
||||
enc.Encode(result)
|
||||
}
|
||||
|
||||
/*
|
||||
curl "http://127.0.0.1:8000/getcost?cstmid=vdf&subj=rif&dest=0257@amount=100"
|
||||
*/
|
||||
func debitSecondsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
enc := json.NewEncoder(w)
|
||||
r.ParseForm()
|
||||
cstmid, ok1 := r.Form["cstmid"]
|
||||
subj, ok2 := r.Form["subj"]
|
||||
dest, ok3 := r.Form["dest"]
|
||||
amount_s, ok4 := r.Form["amount"]
|
||||
amount, err := strconv.ParseFloat(amount_s[0], 64)
|
||||
if !ok1 || !ok2 || !ok3 || !ok4 || err != nil {
|
||||
enc.Encode(IncorrectParameters{"Incorrect parameters"})
|
||||
return
|
||||
}
|
||||
arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
|
||||
result := Debit(arg, "Storage.DebitSeconds")
|
||||
enc.Encode(result)
|
||||
}
|
||||
|
||||
func listenToHttpRequests() {
|
||||
http.HandleFunc("/", statusHandler)
|
||||
http.HandleFunc("/getcost", getCostHandler)
|
||||
http.HandleFunc("/debitbalance", debitBalanceHandler)
|
||||
http.HandleFunc("/debitsms", debitSMSHandler)
|
||||
http.HandleFunc("/debitseconds", debitSecondsHandler)
|
||||
log.Print("The server is listening on ", *httpApiAddress)
|
||||
http.ListenAndServe(*httpApiAddress, nil)
|
||||
}
|
||||
|
||||
@@ -2,25 +2,24 @@ package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"github.com/rif/cgrates/timespans"
|
||||
"log"
|
||||
//"runtime"
|
||||
"runtime"
|
||||
"time"
|
||||
"flag"
|
||||
)
|
||||
|
||||
var (
|
||||
raterAddress = flag.String("rateraddr", "127.0.0.1:2000", "Rater server address (localhost:2000)")
|
||||
jsonRpcAddress = flag.String("jsonrpcaddr", "127.0.0.1:2001", "Json RPC server address (localhost:2001)")
|
||||
httpApiAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:2002)")
|
||||
raterList *RaterList
|
||||
raterAddress = flag.String("rateraddr", "127.0.0.1:2000", "Rater server address (localhost:2000)")
|
||||
jsonRpcAddress = flag.String("jsonrpcaddr", "127.0.0.1:2001", "Json RPC server address (localhost:2001)")
|
||||
httpApiAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:2002)")
|
||||
raterList *RaterList
|
||||
)
|
||||
|
||||
|
||||
/*
|
||||
The function that gets the information from the raters using balancer.
|
||||
*/
|
||||
func CallRater(key *timespans.CallDescriptor) (reply *timespans.CallCost) {
|
||||
func GetCost(key *timespans.CallDescriptor) (reply *timespans.CallCost) {
|
||||
err := errors.New("") //not nil value
|
||||
for err != nil {
|
||||
client := raterList.Balance()
|
||||
@@ -38,11 +37,29 @@ func CallRater(key *timespans.CallDescriptor) (reply *timespans.CallCost) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The function that gets the information from the raters using balancer.
|
||||
*/
|
||||
func Debit(key *timespans.CallDescriptor, method string) (reply float64) {
|
||||
err := errors.New("") //not nil value
|
||||
for err != nil {
|
||||
client := raterList.Balance()
|
||||
if client == nil {
|
||||
log.Print("Waiting for raters to register...")
|
||||
time.Sleep(1 * time.Second) // wait one second and retry
|
||||
} else {
|
||||
err = client.Call(method, *key, &reply)
|
||||
if err != nil {
|
||||
log.Printf("Got en error from rater: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
//runtime.GOMAXPROCS(runtime.NumCPU() - 1)
|
||||
runtime.GOMAXPROCS(runtime.NumCPU() - 1)
|
||||
raterList = NewRaterList()
|
||||
|
||||
go StopSingnalHandler()
|
||||
|
||||
@@ -2,10 +2,10 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/rif/cgrates/timespans"
|
||||
"log"
|
||||
"net"
|
||||
"net/rpc"
|
||||
"net/rpc/jsonrpc"
|
||||
"log"
|
||||
)
|
||||
|
||||
type Responder byte
|
||||
@@ -13,9 +13,24 @@ type Responder byte
|
||||
/*
|
||||
RPC method thet provides the external RPC interface for getting the rating information.
|
||||
*/
|
||||
func (r *Responder) Get(arg timespans.CallDescriptor, replay *timespans.CallCost) error {
|
||||
*replay = *CallRater(&arg)
|
||||
return nil
|
||||
func (r *Responder) GetGost(arg timespans.CallDescriptor, replay *timespans.CallCost) (err error) {
|
||||
*replay = *GetCost(&arg)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Responder) DebitBalance(arg timespans.CallDescriptor, replay *float64) (err error) {
|
||||
*replay = Debit(&arg, "Storage.DebitCents")
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Responder) DebitSMS(arg timespans.CallDescriptor, replay *float64) (err error) {
|
||||
*replay = Debit(&arg, "Storage.DebitSMS")
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Responder) DebitSeconds(arg timespans.CallDescriptor, replay *float64) (err error) {
|
||||
*replay = Debit(&arg, "Storage.DebitSeconds")
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -31,7 +31,31 @@ func (s *Storage) GetCost(cd timespans.CallDescriptor, reply *timespans.CallCost
|
||||
descriptor.StorageGetter = s.sg
|
||||
r, e := descriptor.GetCost()
|
||||
*reply, err = *r, e
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Storage) DebitCents(cd timespans.CallDescriptor, reply *float64) (err error) {
|
||||
descriptor := &cd
|
||||
descriptor.StorageGetter = s.sg
|
||||
r, e := descriptor.DebitCents()
|
||||
*reply, err = r, e
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Storage) DebitSMS(cd timespans.CallDescriptor, reply *float64) (err error) {
|
||||
descriptor := &cd
|
||||
descriptor.StorageGetter = s.sg
|
||||
r, e := descriptor.DebitSMS()
|
||||
*reply, err = r, e
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Storage) DebitSeconds(cd timespans.CallDescriptor, reply *float64) (err error) {
|
||||
descriptor := &cd
|
||||
descriptor.StorageGetter = s.sg
|
||||
e := descriptor.DebitSeconds()
|
||||
*reply, err = 0.0, e
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -36,6 +36,7 @@ type CallDescriptor struct {
|
||||
TOR int
|
||||
CstmId, Subject, DestinationPrefix string
|
||||
TimeStart, TimeEnd time.Time
|
||||
Amount float64
|
||||
ActivationPeriods []*ActivationPeriod
|
||||
StorageGetter StorageGetter
|
||||
}
|
||||
@@ -237,6 +238,27 @@ func (cd *CallDescriptor) GetMaxSessionTime(maxSessionSeconds int) (seconds int,
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (cd *CallDescriptor) DebitCents() (left float64, err error) {
|
||||
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
|
||||
return userBudget.debitMoneyBudget(cd.StorageGetter, cd.Amount), nil
|
||||
}
|
||||
return 0.0, err
|
||||
}
|
||||
|
||||
func (cd *CallDescriptor) DebitSMS() (left float64, err error) {
|
||||
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
|
||||
return userBudget.debitSMSBuget(cd.StorageGetter, cd.Amount)
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
func (cd *CallDescriptor) DebitSeconds() (err error) {
|
||||
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
|
||||
return userBudget.debitMinutesBudget(cd.StorageGetter, cd.Amount, cd.DestinationPrefix)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
The output structure that will be returned with the call cost information.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ Structure conatining information about user's credit (minutes, cents, sms...).'
|
||||
type UserBudget struct {
|
||||
Id string
|
||||
Credit float64
|
||||
SmsCredit int
|
||||
SmsCredit float64
|
||||
ResetDayOfTheMonth int
|
||||
TariffPlanId string
|
||||
tariffPlan *TariffPlan
|
||||
@@ -22,6 +22,9 @@ type UserBudget struct {
|
||||
mux sync.RWMutex
|
||||
}
|
||||
|
||||
/*
|
||||
Error type for overflowed debit methods.
|
||||
*/
|
||||
type AmountTooBig byte
|
||||
|
||||
func (a AmountTooBig) Error() string {
|
||||
@@ -52,7 +55,7 @@ Serializes the user budget for the storage. Used for key-value storages.
|
||||
*/
|
||||
func (ub *UserBudget) store() (result string) {
|
||||
result += strconv.FormatFloat(ub.Credit, 'f', -1, 64) + ";"
|
||||
result += strconv.Itoa(ub.SmsCredit) + ";"
|
||||
result += strconv.FormatFloat(ub.SmsCredit, 'f', -1, 64) + ";"
|
||||
result += strconv.Itoa(ub.ResetDayOfTheMonth) + ";"
|
||||
result += ub.TariffPlanId + ";"
|
||||
for _, mb := range ub.MinuteBuckets {
|
||||
@@ -72,7 +75,7 @@ De-serializes the user budget for the storage. Used for key-value storages.
|
||||
func (ub *UserBudget) restore(input string) {
|
||||
elements := strings.Split(input, ";")
|
||||
ub.Credit, _ = strconv.ParseFloat(elements[0], 64)
|
||||
ub.SmsCredit, _ = strconv.Atoi(elements[1])
|
||||
ub.SmsCredit, _ = strconv.ParseFloat(elements[1], 64)
|
||||
ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[2])
|
||||
ub.TariffPlanId = elements[3]
|
||||
for _, mbs := range elements[4 : len(elements)-1] {
|
||||
@@ -193,7 +196,7 @@ func (ub *UserBudget) debitMinutesBudget(sg StorageGetter, amount float64, prefi
|
||||
Debits some amount of user's SMS budget. Returns the remaining SMS in user's budget.
|
||||
If the amount is bigger than the budget than nothing wil be debited and an error will be returned
|
||||
*/
|
||||
func (ub *UserBudget) debitSMSBuget(sg StorageGetter, amount int) (int, error) {
|
||||
func (ub *UserBudget) debitSMSBuget(sg StorageGetter, amount float64) (float64, error) {
|
||||
ub.mux.Lock()
|
||||
defer ub.mux.Unlock()
|
||||
if ub.SmsCredit < amount {
|
||||
|
||||
Reference in New Issue
Block a user