#include "../include/includes.h" #include "../include/ppsm.h" #include "../include/ramdata.h" #include "../include/ppsinf.h" #include "../include/message.h" #include "../include/iofunc.h" #include "../include/version.h" #include "../include/pps_public.h" #include "../include/cdrme.h" #include "../include/param.h" #include "../include/plat_inc.h" #include "../../../../plat/scf/src/include/scfmsg.h" #include "../../../../plat/scf/src/include/scfdef.h" #include "../include/ppsMibTable.h" #include "../include/mfunc.h" #include extern PPSParamStruct ppsParam; extern struct timeval tvnow; extern _ram_data *ramshm_ptr; extern _state_machine *smshm_ptr;; extern int SendUSSDRequest(u_short portid, char *ussd_info); extern int smppSendMsg(u_char *peerNumber,u_char *msg,u_char serviceNumPosition); extern int StuffCapMessage(CapArg capArg, PCAP_Message pcap_message); extern int ppsDebugCapMsg(CAP_Message *cap_message,int flag); extern BOOL isPromotionCanBeTransfered(_account_info *accountInfo); extern BOOL isPromotionFirstTransfered(_account_info *accountInfo); extern void SendManualOperationCDR(_account_info *caller_info,_account_info *called_info,int charge); extern int get_transfer_resolution(); extern u_short debug_messages; extern int logMsgFlag; static double feeAsciiToFloat(u_char *fee); ulong getSystemCurrencyResolution(); #define MAX_FEE_LENGTH 7 enum transfeeAccountState { S_TRANSFER_IDLE, S_INPUT_DESTNUMBER, S_WART_INPUT_DESTNUMBER, S_INPUT_DESTNUMBER_AGAIN, S_WART_INPUT_DESTNUMBER_AGAIN, S_MATCH_DESTNUMBER, S_DESTNUMBER_NOT_MATCHED, S_TRANSFER_CHECK_DSTNUMBER, S_TRANSFER_CHECK_TRANSFERED_FEE, S_FULL_PARTIAL_TRANSFER_CHOICE, S_WAIT_FULL_PARTIAL_TRANSFER_CHOICE, S_INPUT_FEE_TRANSFERED, S_WAIT_INPUT_FEE_TRANSFERED, S_PLAY_TRANSFERED_FEE_ERROR, S_WRONG_INPUT_FEE, S_TRANSFER_CONFIRM, S_PLAY_TRANSFER_CONFIRM_SUCCESS, S_WAIT_TRANSFER_CONFIRM, S_TRANSFER_PROCESSING, S_PLAY_TRANSFERED_FEE_SUCCESS, S_CHECK_USSD_INPUT, S_USSD_FT_ALL_IN_ONE_INPUT, S_USSD_FT_REST_START, S_TRANSFER_EXIT, }; enum transfer_mode{ FULL_TRANSFER_MODE, PARTIAL_TRANSFER_MODE, }; #define changeTransferState(portid,val) do { \ feeTransfer = &shmp->process_info.ppsService.feeTransfer;\ feeTransfer->state = val;\ shmp->process_info.serviceInput = 0;\ shmp->process_info.funnel = 0;\ pps_print_event(shmp->process_info.logMsisdn,"[%05d]\33[32m%s\33[0m transfer to state \33[36m%s\33[0m", portid, __FUNCTION__, #val); \ } while(0) u8 getTransferState(u_short portid) { _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; return shmp->process_info.ppsService.feeTransfer.state; } void playPromptAndCollectVoice(u_short portid,u_short voiceID,u8 inputLen) { _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; shmp->process_info.funnel = 0; shmp->process_info.srfRelease = 0; shmp->process_info.voiceID = voiceID; shmp->process_info.maxPCUInfoLen = inputLen; shmp->process_info.endOfReplyDigit[0] = 1; shmp->process_info.endOfReplyDigit[1] = 12; SendPromptAndCollectUserInfo(portid); } void playPromptVoice(u_short portid,u_short voiceID) { _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; shmp->process_info.funnel = 0; shmp->process_info.srfRelease = 0; shmp->process_info.voiceID = voiceID; SendSrfPlayAnnouncement(portid); } void clearTransferInfo(u_short portid) { _state_data *shmp; PutLogFunID("clearTransferInfo"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; memset(&shmp->process_info.ppsService.feeTransfer,0,sizeof(TRANSFER_FEE)); } int WaitingForInput(_state_data *shmp,u8 *inputMsg) { int retval = NO_INPUT,dlgid,msglen,len; CAP_Message capmsg; CapArg capArg; CapPromptAndCollectUserInformation *pPCUI; PutLogFunID("WaitingForInputTransferOutAccount"); dlgid = shmp->context_info.dialogue_id; if(!ReadScfMsg(&capmsg,dlgid)) { return retval; } #if DEBUG if(debug_messages<=MAX_DEBUG_MESSAGES) if((logMsgFlag & 0x04) || (logMsgFlag & 0x02) || shmp->process_info.logMsisdn) { debug_messages ++; ppsDebugCapMsg(&capmsg,0); } #endif switch(capmsg.msgOperaCode) { case CAP_OC_PromptAndCollectUserInformation: AddPPSStatistics(MIBPPS_PCUI_RES,shmp->process_info.dir); shmp->process_info.funnel = 0; msglen = capmsg.msgContent[3]*256 + capmsg.msgContent[4]; capArg.version = shmp->context_info.acn_ver; if(decode_capmsg((char *)&capmsg.msgContent[5], msglen, capmsg.msgOperaCode, CAP_CONFIRM, &capArg)<0) { return (retval = INPUT_ERROR_EXIT); } pPCUI=&capArg.msg_list.promptAndCollectUserInformationArg; len = pPCUI->digitsResponse[0]; if(len > MAX_IVR_INPUT_LEN) len = MAX_IVR_INPUT_LEN; if(pPCUI->digitsResponse[1] & 0x20) { pPCUI->digitsResponse[len] |=0xF0; } ppsBcdToAsciiR((char *)inputMsg,&pPCUI->digitsResponse[2],2*(len-1)); StringCut((char *)inputMsg,'F'); retval = INPUT_SUCCESS; break; case CAP_O_UABORT: case CAP_O_PABORT: default: retval = INPUT_ERROR_EXIT; break; } return retval; } static double asciiFeeToFloat(u_char *feeChar) { u_char *pFloat; double value; u8 i,len,Btimes = 0; len = strlen((char *)feeChar); if(strlen((char *)feeChar) > MAX_FEE_LENGTH) return -1; for(i = 0;i < len;i++) {/* only '0' - '9' and 'B' are allowed */ if(feeChar[i] == 'B') Btimes++; if(feeChar[i] < '0' && feeChar[i] > '9' && feeChar[i] != 'B') return -1; } if(Btimes > 1)/* 'B' only one time */ return -1; if(feeChar[0] == 'B') return -1; pFloat = (u_char *)strchr((char *)feeChar,'B'); if(pFloat != NULL) *pFloat = '.'; value = feeAsciiToFloat(feeChar); if(value <= 0) return -1; return value; } ulong getSystemCurrencyResolution() { long resolution; switch(ppsParam.ppsTables.promptResolution[0].currencyResolution) { case 0: resolution = 1; break; case 1: resolution = 10; break; case 2: default: resolution = 100; break; } return resolution; } static int WaitingForInputTransferOutFee(_state_data *shmp) { u_char input_msg[64] = {0}; double fee; ulong resolution = 1; int result; PutLogFunID("WaitingForInputTransferOutFee"); memset(input_msg,0,64); result = WaitingForInput(shmp,input_msg); if(result != INPUT_SUCCESS) return result; fee = asciiFeeToFloat(input_msg); if(fee <= 0 ) return 2;/* format error */ if(get_transfer_resolution()) resolution = getSystemCurrencyResolution(); shmp->process_info.ppsService.feeTransfer.fee = (int)(fee*resolution); return result; } int WaitingForInputTransferOutAccount(_state_data *shmp) { u_char input_msg[64] = {0}; int result; PutLogFunID("WaitingForInputTransferOutFee"); memset(input_msg,0,64); if(shmp->process_info.ussd_transfer_one_input_flag ==1 ) { result = INPUT_SUCCESS; strcpy((char *)input_msg, shmp->process_info.tmpDigits); } else result = WaitingForInput(shmp,input_msg); if(result != INPUT_SUCCESS) return result; CutUnknownPrefix((char *)input_msg); if((strlen((char *)input_msg) > MAX_ASCII_NUMBER_LEN) ||!strcmp((char *)shmp->caller_info.number, (char *)input_msg)) { if(shmp->process_info.serviceInput++>=SERVICE_INPUT_NUM) { return (result = INPUT_ERROR_EXIT); } return (result = INPUT_ERROR_REINPUT); } memset(&shmp->called_info,0,sizeof(_account_info)); strcpy((char *)shmp->called_info.number, (char *)input_msg); if(GetAccountPos(&shmp->called_info) == FALSE) { if(shmp->process_info.serviceInput++>=SERVICE_INPUT_NUM) { return (result = INPUT_ERROR_EXIT); } return (result = INPUT_ERROR_REINPUT); } if(get_transfer_status_normal_flag()) { int status = GetAccountStatus(&shmp->called_info); if(status != T_NORMAL && status != T_FRESH && status != T_SUSPEND) { if(shmp->process_info.serviceInput++>=SERVICE_INPUT_NUM) { return (result = INPUT_ERROR_EXIT); } return (result=INPUT_ERROR_REINPUT); } } return result; } void saveFirstInputtedTransferOutAccount(_state_data *shmp) { memcpy(&shmp->process_info.ppsService.feeTransfer.account,&shmp->called_info,sizeof(_account_info)); } int matchTwoInpuutedTransferOutAccount(_state_data *shmp) { if(!strcmp((char *)shmp->process_info.ppsService.feeTransfer.account.number, (char *)shmp->called_info.number)) return 1; return 0; } static int WaitForTransferMode(_state_data *shmp) { u_char input_msg[64] = {0}; int result; PutLogFunID("WaitForTransferMode"); memset(input_msg,0,64); result = WaitingForInput(shmp,input_msg); if(result != INPUT_SUCCESS) return result; if(input_msg[0] < '0' || input_msg[0] > '1') { if(shmp->process_info.serviceInput++>=SERVICE_INPUT_NUM) { return INPUT_ERROR_EXIT; } return INPUT_ERROR_REINPUT; } shmp->process_info.ppsService.feeTransfer.transferMode = input_msg[0]; return result; } static int WaitForChoice(_state_data *shmp) { u_char input_msg[64] = {0}; int result; PutLogFunID("WaitForChoice"); memset(input_msg,0,64); result = WaitingForInput(shmp,input_msg); if(result != INPUT_SUCCESS) return result; if(input_msg[0] < '0' || input_msg[0] > '3') { if(shmp->process_info.serviceInput++>=SERVICE_INPUT_NUM) { return INPUT_ERROR_EXIT; } return INPUT_ERROR_REINPUT; } shmp->process_info.ppsService.feeTransfer.transferMode = input_msg[0]; return result; } static int WaitForChoice_chargeOrTransfer(_state_data *shmp) { u_char input_msg[64] = {0}; int result; PutLogFunID("WaitForChoice"); memset(input_msg,0,64); result = WaitingForInput(shmp,input_msg); if(result != INPUT_SUCCESS) return result; if(input_msg[0] < '1' || input_msg[0] > '2') { if(shmp->process_info.serviceInput++>=SERVICE_INPUT_NUM) { return INPUT_ERROR_EXIT; } return INPUT_ERROR_REINPUT; } shmp->process_info.ppsService.feeTransfer.transferMode = input_msg[0]; return result; } int getInputtedChoice(_state_data *shmp) { return shmp->process_info.ppsService.feeTransfer.transferMode - '0'; } long GetPromotionExpiration(_account_info *ptr) { _prepaid_data *shmp=&ramshm_ptr->prepaid_data; PutLogFunID("GetIncomingExpiration"); return (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT) ? shmp->prepaid_info[ptr->head][ptr->tail].promo_date : (tvnow.tv_sec+1); } float GetPromotion(_account_info *ptr) { _prepaid_data *shmp=&ramshm_ptr->prepaid_data; PutLogFunID("GetIncomingExpiration"); return (ptr->head < MSISDN_HEAD_NUM && ptr->tail < UNIT_STORE_ACCOUNT) ? shmp->prepaid_info[ptr->head][ptr->tail].promo_balance : 0; } int checkTransferedPartialFee(_account_info *callerInfo,float feeTransfered) { float balance=0; BOOL balanceExpired=FALSE,promotionExpired=FALSE; if(isPromotionCanBeTransfered(callerInfo)) { if(GetExpiration(callerInfo) <= tvnow.tv_sec) balanceExpired = TRUE; if(GetPromotionExpiration(callerInfo) <= tvnow.tv_sec) promotionExpired = TRUE; if(balanceExpired && promotionExpired) return CHECK_TRANSFERED_FEE_EXPIERED; if(!balanceExpired) balance += GetBalanceWithOutPromotion(callerInfo->head,callerInfo->tail); if(!promotionExpired) balance += GetPromotion(callerInfo); } else { if(GetExpiration(callerInfo) <= tvnow.tv_sec) return CHECK_TRANSFERED_FEE_EXPIERED; balance = GetBalanceWithOutPromotion(callerInfo->head,callerInfo->tail); } if(balance < feeTransfered || feeTransfered<= 0) return CHECK_TRANSFERED_FEE_INSUFFIENT; return CHECK_TRANSFERED_FEE_OK; } int GetBalanceWithOutPromotion(int head, int tail) { _prepaid_data *shmp=&ramshm_ptr->prepaid_data; PutLogFunID("getBalanceWithOutPromotion"); if (head < MSISDN_HEAD_NUM && tail < UNIT_STORE_ACCOUNT) return shmp->prepaid_info[head][tail].balance; return FALSE; } int checkTransferedFullFee(_state_data *shmp) { float balance; if(GetBalance(&shmp->caller_info) <= 0) return CHECK_TRANSFERED_FEE_INSUFFIENT; if(GetExpiration(&shmp->caller_info) < (tvnow.tv_sec+1) && GetPromotionExpiration(&shmp->caller_info) < (tvnow.tv_sec+1)) return CHECK_TRANSFERED_FEE_EXPIERED; if(isPromotionCanBeTransfered(&shmp->caller_info)) { balance = GetAccountBalance(shmp->caller_info.head,shmp->caller_info.tail); } else { balance = GetBalanceWithOutPromotion(shmp->caller_info.head,shmp->caller_info.tail); } if(balance<=0) return CHECK_TRANSFERED_FEE_INSUFFIENT; shmp->process_info.ppsService.feeTransfer.fee = balance; return CHECK_TRANSFERED_FEE_OK; } static int expieredDaysTransfer_not_used(_account_info *callerInfo,_account_info *destInfo,float transferedFee,float promotion) { _prepaid_data *prepaidPoint=&ramshm_ptr->prepaid_data; _prepaid_info *pcalled,*pcaller; float balance,daysPerBalance,valid_time; long diff; COSTable *cosTableItem; pcalled = &prepaidPoint->prepaid_info[destInfo->head][destInfo->tail]; pcaller = &prepaidPoint->prepaid_info[callerInfo->head][callerInfo->tail]; cosTableItem = &ppsParam.ppsTables.cosTable[pcalled->cos_id%MaxCosTableItem]; if(transferedFee > 0) { balance = pcaller->balance; diff = GetExpiration(callerInfo) - tvnow.tv_sec; if(balance == 0) daysPerBalance = 0; else daysPerBalance = diff/balance; valid_time = transferedFee*daysPerBalance; pcalled->mo_expiration_date = valid_time + pcalled->mo_expiration_date; if(cosTableItem->accountValidity[0].maxAccountValidityDays<=0) cosTableItem->accountValidity[0].maxAccountValidityDays = 730; if(pcalled->mo_expiration_date > tvnow.tv_sec+ cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600) pcalled->mo_expiration_date = tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600; } if(promotion > 0) { balance = pcaller->promo_balance; diff = GetPromotionExpiration(callerInfo) - tvnow.tv_sec; if(balance == 0) daysPerBalance = 0; else daysPerBalance = diff/balance; valid_time = promotion*daysPerBalance; pcalled->promo_date = valid_time + pcalled->promo_date; if(cosTableItem->accountValidity[0].maxAccountValidityDays<=0) cosTableItem->accountValidity[0].maxAccountValidityDays = 730; if(pcalled->promo_date > tvnow.tv_sec+ cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600) pcalled->promo_date = tvnow.tv_sec + cosTableItem->accountValidity[0].maxAccountValidityDays*24*3600; } return 1; } static int expieredDaysTransfer(_account_info *callerInfo,_account_info *destInfo,float transferedFee,float promotion) { _prepaid_data *prepaidPoint=&ramshm_ptr->prepaid_data; _prepaid_info *pcalled,*pcaller; if(get_not_change_transfer_expiry_date()) {return 1;} pcalled = &prepaidPoint->prepaid_info[destInfo->head][destInfo->tail]; pcaller = &prepaidPoint->prepaid_info[callerInfo->head][callerInfo->tail]; if(transferedFee > 0) { if(pcalled->mo_expiration_date < pcaller->mo_expiration_date) pcalled->mo_expiration_date = pcaller->mo_expiration_date; if(pcalled->mt_expiration_date < pcaller->mt_expiration_date) pcalled->mt_expiration_date = pcaller->mt_expiration_date; } if(promotion > 0) { if(pcalled->promo_date < pcaller->promo_date) pcalled->promo_date = pcaller->promo_date; } return 1; } int poolTransferAccount(_account_info *callerInfo,_account_info *destInfo,float transferedFee) { /*Notice: Be sure to call checkTransferedPartialFee() first to check */ u_long instance; int retval=0; _prepaid_data *prepaidPoint=&ramshm_ptr->prepaid_data; _prepaid_info *pcaller,*pcalled; float diff=0; double oldCallerBalance,oldCallerPromo,oldCalledBalance,oldCalledPromo; BOOL balanceExpired=FALSE,promotionExpired=FALSE; if(transferedFee == 0) { //pps_print_error(0,"%s no need to transfer fee:%0.4f to %s",callerInfo->number,transferedFee,destInfo->number); return -1; } pcalled = &prepaidPoint->prepaid_info[destInfo->head][destInfo->tail]; oldCalledBalance = pcalled->balance; oldCalledPromo = pcalled->promo_balance; pcaller = &prepaidPoint->prepaid_info[callerInfo->head][callerInfo->tail]; oldCallerBalance = pcaller->balance; oldCallerPromo = pcaller->promo_balance; if(isPromotionCanBeTransfered(callerInfo) == FALSE) { expieredDaysTransfer(callerInfo,destInfo,transferedFee,0); pcalled->balance += transferedFee; pcaller->balance -= transferedFee; } else { if(GetExpiration(callerInfo) <= tvnow.tv_sec) balanceExpired = TRUE; if(GetPromotionExpiration(callerInfo) <= tvnow.tv_sec) promotionExpired = TRUE; if(balanceExpired == TRUE) { expieredDaysTransfer(callerInfo,destInfo,0,transferedFee); pcalled->promo_balance += transferedFee; pcaller->promo_balance -= transferedFee; } else if(promotionExpired == TRUE) { expieredDaysTransfer(callerInfo,destInfo,transferedFee,0); pcalled->balance += transferedFee; pcaller->balance -= transferedFee; } else { if(isPromotionFirstTransfered(callerInfo) == FALSE) { if(transferedFee > pcaller->balance) { diff = transferedFee - pcaller->balance; expieredDaysTransfer(callerInfo,destInfo,transferedFee - diff,diff); pcalled->balance += transferedFee - diff; pcaller->balance = 0; pcalled->promo_balance += diff; pcaller->promo_balance -= diff; } else { expieredDaysTransfer(callerInfo,destInfo,transferedFee,0); pcalled->balance += transferedFee; pcaller->balance -= transferedFee; } } else if(isPromotionFirstTransfered(callerInfo) == TRUE) { if(transferedFee > pcaller->promo_balance) { diff = transferedFee - pcaller->promo_balance; expieredDaysTransfer(callerInfo,destInfo,diff,transferedFee - diff); pcalled->promo_balance += transferedFee - diff; pcaller->promo_balance = 0; pcalled->balance += diff; pcaller->balance -= diff; } else { expieredDaysTransfer(callerInfo,destInfo,0,transferedFee); pcalled->promo_balance += transferedFee; pcaller->promo_balance -= transferedFee; } } } } UpdateAccountStatus(destInfo->head, destInfo->tail, T_NORMAL); instance = destInfo->head * UNIT_STORE_ACCOUNT + destInfo->tail; if(pcalled->balance >= 0) { UpdateAccountOverdraft(destInfo->head, destInfo->tail, 0); } resetCMBTimes(destInfo); SendAccountRealSync(instance, (pcalled->balance-oldCalledBalance), (pcalled->promo_balance-oldCalledPromo), OMC_OCODE_EDIT); instance = callerInfo->head * UNIT_STORE_ACCOUNT + callerInfo->tail; SendAccountRealSync(instance, (pcaller->balance-oldCallerBalance), (pcaller->promo_balance-oldCallerPromo), OMC_OCODE_EDIT); return (retval = 1); } void notifyUserTransferResult(_state_data *shmp,u8 callerOrCalled) { u_char msgSend[MAX_SMS_LEN*4] = {0}, /*tmpbuf[64]={0},*/ buf[MAX_SMS_LEN*2]={0}; float balance; //u_char expire_date[128]={0},promotion_expire_date[128]={0}; //int i,j; u_char dayTimeReadable[32]={0}; char tmpCaller[32],tmpCalled[32]; balance = shmp->process_info.ppsService.feeTransfer.fee; if(balance == 0) { pps_print_error(shmp->process_info.logMsisdn,"[%05d]No need to notify transfer result,fee:%0.4f",shmp->process_info.portid,balance); return; } ppsgetdaytime_readFormat((char *)dayTimeReadable); switch(callerOrCalled) { case NOTIFY_CALLER: strcpy((char *)msgSend, (char *)getSmsSentenceNative(0, SMS_TRANSFERED_OUT)); break; case NOTIFY_CALLED: default: strcpy((char *)msgSend, (char *)getSmsSentenceNative(0,SMS_TRANSFERED_IN)); break; } fillMoneyToContent(balance, (char *)buf); strcat((char *)msgSend, (char *)buf); switch(callerOrCalled) { case NOTIFY_CALLER: strcpy(tmpCaller, (char *)shmp->process_info.ppsService.feeTransfer.account.number); strcpy(tmpCalled, (char *)shmp->caller_info.number); cliManipulationFunction(tmpCaller,tmpCalled); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0,SMS_TO), tmpCaller); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0,SMS_ON), dayTimeReadable); { char tmp_info[256]; GetAccountPromptInfo(&shmp->caller_info, tmp_info); strcat((char *)msgSend, tmp_info); smppSendMsg(shmp->caller_info.number,msgSend,FeeTransferPosition); } /* smppSendMsg(shmp->caller_info.number,msgSend,FeeTransferPosition); i = shmp->caller_info.head%MSISDN_HEAD_NUM; j = shmp->caller_info.tail%UNIT_STORE_ACCOUNT; AsciiTime(expire_date,ramshm_ptr->prepaid_data.prepaid_info[i][j].mo_expiration_date); AsciiTime(promotion_expire_date,ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_date); smppSendAccountInfo(shmp->caller_info.number, ppsParam.ppsTables.serviceNumber[FeeTransferPosition].number, (long)ramshm_ptr->prepaid_data.prepaid_info[i][j].balance,expire_date, (long)ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_balance,promotion_expire_date, 0,"","", ramshm_ptr->prepaid_data.prepaid_info[i][j].language_type ); */ break; case NOTIFY_CALLED: default: strcpy(tmpCaller, (char *)shmp->caller_info.number); strcpy(tmpCalled, (char *)shmp->process_info.ppsService.feeTransfer.account.number); cliManipulationFunction(tmpCaller,tmpCalled); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0, SMS_FROM), tmpCaller); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0, SMS_ON), dayTimeReadable); { char tmp_info[256]; GetAccountPromptInfo(&shmp->process_info.ppsService.feeTransfer.account, tmp_info); strcat((char *)msgSend, tmp_info); smppSendMsg(shmp->process_info.ppsService.feeTransfer.account.number,msgSend,FeeTransferPosition); } /* smppSendMsg(shmp->process_info.ppsService.feeTransfer.account.number,msgSend,FeeTransferPosition); i = shmp->process_info.ppsService.feeTransfer.account.head; j = shmp->process_info.ppsService.feeTransfer.account.tail; AsciiTime(expire_date,ramshm_ptr->prepaid_data.prepaid_info[i][j].mo_expiration_date); AsciiTime(promotion_expire_date,ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_date); smppSendAccountInfo(shmp->process_info.ppsService.feeTransfer.account.number, ppsParam.ppsTables.serviceNumber[FeeTransferPosition].number, (long)ramshm_ptr->prepaid_data.prepaid_info[i][j].balance,expire_date, (long)ramshm_ptr->prepaid_data.prepaid_info[i][j].promo_balance,promotion_expire_date, 0,"","", ramshm_ptr->prepaid_data.prepaid_info[i][j].language_type); */ break; } } void notifyUserTransferResult_1(_account_info *srcUsr, _account_info *dstUsr, int amount, u8 callerOrCalled) { u_char msgSend[MAX_SMS_LEN*4] = {0}, /*tmpbuf[64]={0}, */buf[MAX_SMS_LEN*2]={0}; float balance; //u_char expire_date[128]={0},promotion_expire_date[128]={0}; //int i,j; u_char dayTimeReadable[32]={0}; char tmpCaller[32],tmpCalled[32]; balance = amount; if(balance == 0.0) { return; } ppsgetdaytime_readFormat((char *)dayTimeReadable); switch(callerOrCalled) { case NOTIFY_CALLER: strcpy((char *)msgSend, (char *)getSmsSentenceNative(0,SMS_TRANSFERED_OUT)); break; case NOTIFY_CALLED: default: strcpy((char *)msgSend, (char *)getSmsSentenceNative(0,SMS_TRANSFERED_IN)); break; } fillMoneyToContent(balance, (char *)buf); strcat((char *)msgSend, (char *)buf); switch(callerOrCalled) { case NOTIFY_CALLER: strcpy(tmpCaller, (char *)dstUsr->number); strcpy(tmpCalled, (char *)srcUsr->number); cliManipulationFunction(tmpCaller, tmpCalled); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0,SMS_TO), tmpCaller); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0,SMS_ON), dayTimeReadable); { char tmp_info[256]; GetAccountPromptInfo(srcUsr, tmp_info); strcat((char *)msgSend, tmp_info); smppSendMsg(srcUsr->number, msgSend, FeeTransferPosition); } break; case NOTIFY_CALLED: default: strcpy(tmpCaller, (char *)srcUsr->number); strcpy(tmpCalled, (char *)dstUsr->number); cliManipulationFunction(tmpCaller, tmpCalled); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0, SMS_FROM), tmpCaller); sprintf((char *)msgSend+strlen((char *)msgSend), " %s %s", getSmsSentenceNative(0, SMS_ON), dayTimeReadable); { char tmp_info[256]; GetAccountPromptInfo(dstUsr, tmp_info); strcat((char *)msgSend, tmp_info); smppSendMsg(dstUsr->number, msgSend, FeeTransferPosition); } break; } } void SendTransferCDR(_account_info *caller_info,_account_info *called_info,float charge) { _tocdr_report pcdr; char buf[BUFSIZE]={""}; int fee,balance,len; int head, tail; PutLogFunID("SendManualOperationCDR"); head = caller_info->head; tail = caller_info->tail; memset(&pcdr, 0, sizeof(_tocdr_report)); if (charge > 0) { pcdr.type[0] = CT_TRANFER_IN; pcdr.type[1] = CT_TRANFER_IN>>8; } else if (charge < 0) { pcdr.type[0] = CT_TRANFER_OUT; pcdr.type[1] = CT_TRANFER_OUT>>8; } else { //pps_print_error(0,"transfee fee is %d,%s no need to send cdr at %s", // charge,caller_info->number,__FUNCTION__); return ; } AsciiToBcd(pcdr.seizuretime, ppsgetdaytime(buf), 14); AsciiToBcd(pcdr.answertime, ppsgetdaytime(buf), 14); AsciiToBcd(pcdr.releasetime, ppsgetdaytime(buf), 14); pcdr.duration[0] = 0; fee = (int)charge; fee = abs(fee); memcpy(pcdr.charge,&fee,4); balance = (int) GetAccountBalance(head, tail); memcpy(pcdr.balance,&balance,4); GetAccountMsisdn(head,tail,&pcdr.msisdn[1]); ByteRev(pcdr.msisdn,9,0); pcdr.msisdn[0]=0x91; memcpy(pcdr.caller,pcdr.msisdn,9); buf[0] = 0; pcdr.called[0] = 0x91; len = strlen((char *)called_info->number)%20; ppsAsciiToBcdR(&pcdr.called[1], (char *)called_info->number,(len+1)/2*2); if(len %2) { pcdr.called[(len+1)/2] |= 0xF0; } if(len<21) { pcdr.called[(len+1)/2+1] = 0xFF; } sprintf(buf,"FFFFFFFFFFFFFFFFFF"); AsciiToBcd(pcdr.imsi,buf,16); pcdr.tcos[0] = NORMAL_CLEARING%256; CDRStatistics(&pcdr,charge, 0); StoreCDR(&pcdr); pps_real_update_user_file(head, tail); #if DEBUG if((logMsgFlag & 0x04) || (logMsgFlag & 0x02)) DebugMsg(debugmib.display.asciiOut, "SendTransferCDR"); #endif } static void sendTransferInCDR(_state_data *shmp) { float charge; charge = shmp->process_info.ppsService.feeTransfer.fee; SendTransferCDR(&shmp->process_info.ppsService.feeTransfer.account,&shmp->caller_info,charge); } static void sendTransferOutCDR(_state_data *shmp) { float charge; charge = shmp->process_info.ppsService.feeTransfer.fee; SendTransferCDR(&shmp->caller_info,&shmp->process_info.ppsService.feeTransfer.account,-charge); } void FeeTransferTransaction(_state_data *shmp) { poolTransferAccount(&shmp->caller_info, &shmp->process_info.ppsService.feeTransfer.account, shmp->process_info.ppsService.feeTransfer.fee); notifyUserTransferResult(shmp,NOTIFY_CALLER); notifyUserTransferResult(shmp,NOTIFY_CALLED); sendTransferInCDR(shmp); sendTransferOutCDR(shmp); } int SendTransferInfoPromptToSrf(u_short portid) { int balance,centbalance,hth_b,th_b,h_b,b_b; char expire_date[20]="",buf[BUFSIZE]=""; int resolution=100; int len; _state_data *shmp; int dlgid,invokeid=0; CAP_Message cap_message; CapArg capArg; CapPlayAnnouncement *pPlayAnnouncement; CapMessageID *pMID; u8 transferNumber[MAX_MSISDN_BLEN]; u8 varIndex = 0; PutLogFunID("SendTransferInfoPromptToSrf"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; AddPPSStatistics(MIBPPS_PLAY_ANNOUNCEMENT,shmp->process_info.dir); balance = shmp->process_info.ppsService.feeTransfer.fee; if(balance < 0) balance = 0; AsciiTime(expire_date,GetExpiration(&shmp->caller_info)); dlgid = shmp->context_info.dialogue_id; capArg.ocode = CAP_OC_PlayAnnouncement; capArg.message_flag = REQUEST; capArg.port_id = portid; capArg.dialogue_id = dlgid; capArg.invoke_id = invokeid; capArg.version = shmp->context_info.acn_ver; resolution = getSystemCurrencyResolution(); centbalance = (balance % resolution); balance = (balance / resolution); hth_b = (balance / 10000)%100; th_b = (balance / 1000)%10; h_b = (balance / 100)%10; b_b = (balance % 100); pPlayAnnouncement = &capArg.msg_list.playAnnouncementArg; pPlayAnnouncement->optional_flag = 0x03; pPlayAnnouncement->disconnectFromIPForbidden = 0x01; pPlayAnnouncement->requestAnnouncementComplete = 0x01; pPlayAnnouncement->informationToSend.choice_id = 0x00; pPlayAnnouncement->informationToSend.inbandInfo.messageID.choice_id = 0x03; pMID = &pPlayAnnouncement->informationToSend.inbandInfo.messageID; pMID->variableMessage.elementaryMessageID = GetAccountVoiceID(shmp->caller_info.head,shmp->caller_info.tail)*65536 + INPUT_TRANSFER_CONFIRM; pMID->variableMessage.variableParts.num = 2; pMID->variableMessage.variableParts.variablePart[varIndex].choice_id = 4; sprintf(buf,"%02d",hth_b); ppsAsciiToBcdR(&pMID->variableMessage.variableParts.variablePart[varIndex].price[0], buf,2); sprintf(buf,"%d%d",th_b,h_b); ppsAsciiToBcdR(&pMID->variableMessage.variableParts.variablePart[varIndex].price[1], buf,2); sprintf(buf,"%02d",b_b); ppsAsciiToBcdR(&pMID->variableMessage.variableParts.variablePart[varIndex].price[2], buf,2); sprintf(buf,"%02d",centbalance); ppsAsciiToBcdR(&pMID->variableMessage.variableParts.variablePart[varIndex].price[3], buf,2); varIndex++; len = strlen((char *)shmp->process_info.ppsService.feeTransfer.account.number); ppsAsciiToBcdR(transferNumber, (char *)shmp->process_info.ppsService.feeTransfer.account.number, len); if(len>(MAX_MSISDN_BLEN-1)*2) len = (MAX_MSISDN_BLEN - 1 )*2; pMID->variableMessage.variableParts.variablePart[varIndex].choice_id = 1; pMID->variableMessage.variableParts.variablePart[varIndex].number[0] = (len+1)/2+1; if(len%2==0) { pMID->variableMessage.variableParts.variablePart[varIndex].number[1] = 0x04; memcpy(&pMID->variableMessage.variableParts.variablePart[varIndex].number[2], transferNumber, (len+1)/2); } else { pMID->variableMessage.variableParts.variablePart[varIndex].number[1] = 0x24; memcpy(&pMID->variableMessage.variableParts.variablePart[varIndex].number[2], transferNumber, (len+1)/2); pMID->variableMessage.variableParts.variablePart[varIndex].number[2+(len+1)/2] &=0x0F; } pPlayAnnouncement->informationToSend.inbandInfo.optional_flag = 0x07; pPlayAnnouncement->informationToSend.inbandInfo.numberOfRepetitions = 0x01; pPlayAnnouncement->informationToSend.inbandInfo.duration = 0x00; pPlayAnnouncement->informationToSend.inbandInfo.interval = 0x00; StuffCapMessage(capArg,&cap_message); WriteScfMsg(cap_message); #if DEBUG if(debug_messages<=MAX_DEBUG_MESSAGES) if((logMsgFlag & 0x02)|| shmp->process_info.logMsisdn) { ppsDebugCapMsg(&cap_message,1); debug_messages ++; } #endif return 1; } int getUssdACK_old(u_short portid,u_char *ussd_data) { MapOprSrv_struct opr_srv; u8 data_flow[256]; struct MapPUSSR_Arg *pussr_arg; _state_data *shmp = (_state_data *) smshm_ptr->state_data; if(portid>=MAX_FSM_PROCESS) { return -1; } shmp += (portid); if(!map_get_oprdata(data_flow,shmp->context_info.map_did)) { return 0; } if((data_flow[9] != UnstrctSSReq) || data_flow[1]<14) { if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\n\33[31m portid: %d ,did: %d, wait USSDR_ACK but %d received\33[0m", portid,shmp->context_info.map_did,data_flow[9]); } pps_send_map_close(portid); return -1; } if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\nportid: %d ,did: %d, Get Map opr,type:<%d>, PUSSR ", portid,shmp->context_info.map_did, data_flow[9]); pps_debug_map_msg(data_flow,0); } opr_srv.version = shmp->context_info.acn_ver; opr_srv.message_type = data_flow[9]; opr_srv.message_flag = data_flow[10]; opr_srv.port_id = portid; opr_srv.dialogue_id = shmp->context_info.map_did; if(extract_mapparam(&opr_srv, data_flow[9], data_flow[10], data_flow[14]*256+data_flow[15], &data_flow[16])<=0) { if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\n\33[31mportid: %d ,did: %d, decode PUSSR failed \33[0m", portid,shmp->context_info.map_did); } return -1; } //shmp->context_info.invoke_id = data_flow[11]; pussr_arg = &opr_srv.msg_list.pussr_arg; if(pussr_arg->param_flag != 0x01) { if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\n\33[31mportid: %d ,did: %d, decode ussd failed,no content,param flag:%d \33[0m", portid,shmp->context_info.map_did,pussr_arg->param_flag); } return -1; } switch(pussr_arg->ussd_arg.ussd_scheme & 0x0f) { case 0x00: case 0x0f: /* 7bit */ smppDecodeSM((char *)pussr_arg->ussd_arg.ussd_string.ussd_data, (char *)ussd_data, pussr_arg->ussd_arg.ussd_string.string_len); break; case 0x04: /* 8bit */ default: memcpy(ussd_data, pussr_arg->ussd_arg.ussd_string.ussd_data, pussr_arg->ussd_arg.ussd_string.string_len); break; } if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\nportid: %d ,did: %d, USSD data: \r\n\%s ", portid,shmp->context_info.map_did, ussd_data); } return strlen((char *)ussd_data); } int getUssdACK(u_short portid,u_char *ussd_data) { MapOprSrv_struct opr_srv; u8 data_flow[256]; struct MapUSSR_Res *ussr_ack; _state_data *shmp = (_state_data *) smshm_ptr->state_data; if(portid>=MAX_FSM_PROCESS) { return -1; } shmp += (portid); if(!map_get_oprdata(data_flow,shmp->context_info.map_did)) { return 0; } if((data_flow[9] != UnstrctSSReq) || data_flow[1]<14) { if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\n\33[31m portid: %d ,did: %d, wait USSDR_ACK but %d received\33[0m", portid,shmp->context_info.map_did,data_flow[9]); } pps_send_map_close(portid); return -1; } if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\nportid: %d ,did: %d, Get Map opr,type:<%d>, USSR ", portid,shmp->context_info.map_did, data_flow[9]); pps_debug_map_msg(data_flow,0); } opr_srv.version = shmp->context_info.acn_ver; opr_srv.message_type = data_flow[9]; opr_srv.message_flag = data_flow[10]; opr_srv.port_id = portid; opr_srv.dialogue_id = shmp->context_info.map_did; if(extract_mapparam(&opr_srv, data_flow[9], data_flow[10], data_flow[14]*256+data_flow[15], &data_flow[16])<=0) { if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\n\33[31mportid: %d ,did: %d, decode USSR_ACK failed \33[0m", portid,shmp->context_info.map_did); } return -1; } ussr_ack = &opr_srv.msg_list.ussr_res; if(ussr_ack->param_flag != 0x01) { if((logMsgFlag & 0x01) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\n\33[31mportid: %d ,did: %d, USSR error received,no content,param flag is:%d \33[0m", portid,shmp->context_info.map_did,ussr_ack->param_flag); } return -1; } switch(ussr_ack->ussd_res.ussd_scheme & 0x0f) { case 0x00: case 0x0f: /* 7bit */ smppDecodeSM((char *)ussr_ack->ussd_res.ussd_string.ussd_data, (char *)ussd_data, ussr_ack->ussd_res.ussd_string.string_len); if(ussr_ack->ussd_res.ussd_string.string_len %7 == 0) { int tmplen; tmplen = ussr_ack->ussd_res.ussd_string.string_len*8/7; if(ussd_data[tmplen-1] == 0x0d) /* ussd padding byte: 0x0d */ { ussd_data[tmplen-1] = '\0'; } } break; case 0x04: /* 8bit */ default: memcpy(ussd_data, ussr_ack->ussd_res.ussd_string.ussd_data, ussr_ack->ussd_res.ussd_string.string_len); break; } if((logMsgFlag == 0xff) || shmp->process_info.logMsisdn) { DebugMsg(debugmib.display.asciiOut, "\nportid: %d ,did: %d, USSD data: \r\n\%s ", portid,shmp->context_info.map_did, ussd_data); } return strlen((char *)ussd_data); } int SendServiceNotApplied(u_short portid,u8 ussdSmsFlag,u8 serviceNumberPosition) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_SERVICE_NOT_APPLIED)); switch(ussdSmsFlag) { case USSD_TRANSFER: //SendUSSDRequest(portid,tmp); SendUSSDNotify(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,serviceNumberPosition); break; } return 1; } static int SendTransferRequest(u_short portid,u8 ussdSmsFlag) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_TRANSFER_PROMPT)); switch(ussdSmsFlag) { case USSD_TRANSFER: SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } static int SendReinputTransferRequest(u_short portid,u8 ussdSmsFlag) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_FORMAT_ERROR)); strcat((char *)tmp, (char *)getSmsSentenceNative(0,SMS_TRANSFER_PROMPT)); switch(ussdSmsFlag) { case USSD_TRANSFER: SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } static int SendTransferDstNumberErrorRequest(u_short portid,u8 ussdSmsFlag) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_INVALID_NUMBER)); if(shmp->process_info.ussd_transfer_one_input_flag != 1) { strcat((char *)tmp, (char *)getSmsSentenceNative(0,SMS_TRANSFER_PROMPT)); } switch(ussdSmsFlag) { case USSD_TRANSFER: if(shmp->process_info.ussd_transfer_one_input_flag == 1) SendUSSDNotify(portid, (char *)tmp); else SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } static int SendTransferInsufficientFeeRequest(u_short portid,u8 ussdSmsFlag) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_INSUFFICIENT_FEE)); if(shmp->process_info.ussd_transfer_one_input_flag != 1) { strcat((char *)tmp, (char *)getSmsSentenceNative(0,SMS_TRANSFER_PROMPT)); } switch(ussdSmsFlag) { case USSD_TRANSFER: if(shmp->process_info.ussd_transfer_one_input_flag == 1) SendUSSDNotify(portid, (char *)tmp); else SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } static int SendTransferExpiredAccountRequest(u_short portid,u8 ussdSmsFlag) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_EXPIRED_ACCOUNT)); switch(ussdSmsFlag) { case USSD_TRANSFER: SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } static int SendTransferInfoConfirmRequest(u_short portid,u8 ussdSmsFlag) { _state_data *shmp; //TRANSFER_FEE *transferInfo; float balance; u_char tmp[MAX_SMS_LEN*4] = {0}, /*tmpbuf[64]={0}, */buf[MAX_SMS_LEN*2]={0}; char tmpCaller[32],tmpCalled[32]; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; //transferInfo = &shmp->process_info.ppsService.feeTransfer; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_WILL_TRANSFER_OUT)); balance = shmp->process_info.ppsService.feeTransfer.fee; fillMoneyToContent(balance, (char *)buf); strcat((char *)tmp, (char *)buf); strcpy(tmpCaller, (char *)shmp->process_info.ppsService.feeTransfer.account.number); strcpy(tmpCalled, (char *)shmp->caller_info.number); cliManipulationFunction(tmpCaller,tmpCalled); sprintf((char *)tmp+strlen((char *)tmp), " %s %s.", getSmsSentenceNative(0,SMS_TO), tmpCaller); strcat((char *)tmp, (char *)getSmsSentenceNative(0,SMS_YES_OR_NO)); switch(ussdSmsFlag) { case USSD_TRANSFER: SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } static int SendReinputTransferConfrimRequest(u_short portid,u8 ussdSmsFlag) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_FORMAT_ERROR)); strcat((char *)tmp, (char *)getSmsSentenceNative(0,SMS_YES_OR_NO)); switch(ussdSmsFlag) { case USSD_TRANSFER: SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } int SendTransferSuccessRequest(u_short portid,u8 ussdSmsFlag) { u_char tmp[MAX_SMS_LEN*4] = {0}; _state_data *shmp; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; strcpy((char *)tmp, (char *)getSmsSentenceNative(0,SMS_TRANSFER_SUCCESS)); switch(ussdSmsFlag) { case USSD_TRANSFER: SendPSSREnd(portid, (char *)tmp); //SendUSSDRequest(portid, (char *)tmp); break; case SMS_TRANSFER: default: smppSendMsg(shmp->caller_info.number,tmp,FeeTransferPosition); break; } return 1; } static double feeAsciiToFloat(u_char *fee) { u_char *p; float factor=0.1001; double value=0; if(fee == NULL) return 0; p = fee; while(isdigit(*p)) { value = value*10+(*p-'0'); p++; } if(*p == '.') { p++; while(isdigit(*p)) { value += factor*(*p-'0'); p++; factor *= 0.1001; } } return value; } int getTransferInfo(u_short portid,u_char *ussd_data) {/* format:number#amount */ _state_data *shmp; TRANSFER_FEE *transferInfo; u8 i,len,Btimes = 0,Atimes = 0,Bposition,Aposition,resolution = 1; u8 *p,feeAscii[64]={0}; double fee; PutLogFunID("getTransferInfo"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; len = strlen((char *)ussd_data); for(i = 0;i < len;i++) { if(!isdigit(ussd_data[i]) && ussd_data[i] != '#' && ussd_data[i] != '*' && ussd_data[i] != '.') return -1; if(ussd_data[i] == '#') { Btimes++; Bposition = i; } if(ussd_data[i] == '*' || ussd_data[i] == '.') { Atimes++; Aposition = i; } } if(Btimes != 1 || Atimes > 1) return -1; if(!isdigit(ussd_data[0]) || !isdigit(ussd_data[len - 1])) return -1; if(Atimes >= 1) { if(Bposition >= Aposition) return -1; } p = (u8 *)strchr((char *)ussd_data+1, '#'); if(p == NULL) return -1; if(!isdigit(*(p+1))) return -1; transferInfo = &shmp->process_info.ppsService.feeTransfer; *p = 0; memset(feeAscii,0,64); strcpy((char *)feeAscii, (char *)p+1); p = (u8 *)strchr((char *)feeAscii, '*'); if(p != NULL) { *p = '.'; } if(strlen((char *)feeAscii) > MAX_FEE_LENGTH) return -1; if(get_transfer_resolution()) resolution = getSystemCurrencyResolution(); fee = feeAsciiToFloat(feeAscii); transferInfo->fee = (int)(fee*resolution); if(transferInfo->fee <= 0) return -1; CutUnknownPrefix((char *)ussd_data); if(strlen((char *)ussd_data) > MAX_ASCII_NUMBER_LEN) return -1; memset(transferInfo->account.number,0,MAX_ASCII_NUMBER_LEN); strcpy((char *)transferInfo->account.number, (char *)ussd_data); return 1; } int smppSendMsg(u_char *peerNumber,u_char *msg,u_char serviceNumPosition) { //u_char buf[256]={0}; //int result = 0; PutLogFunID("smppSendMsg"); return smppSendMOSM((char *)peerNumber, (char *)ppsParam.ppsTables.serviceNumber[serviceNumPosition].number , msg, strlen((char *)msg), 0); } int saveTransferSMSACK(u_short portid,u_char *sms) { _state_data *shmp; u8 len; PutLogFunID("saveSMSACK"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; len = strlen((char *)sms) % MAX_INPUT_SMS; memcpy(shmp->process_info.ppsService.feeTransfer.inputSMS,sms,len); shmp->process_info.ppsService.feeTransfer.inputSMS[len] = 0; shmp->process_info.ppsService.feeTransfer.smsTrigger = TRUE; return len; } static int getTransferSMSACK(u_short portid,u_char *sms) { _state_data *shmp; PutLogFunID("getSMSACK"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; if(shmp->process_info.ppsService.feeTransfer.smsTrigger == FALSE) return 0; shmp->process_info.ppsService.feeTransfer.smsTrigger = FALSE; strcpy((char *)sms, (char *)shmp->process_info.ppsService.feeTransfer.inputSMS); return strlen((char *)sms); } static BOOL checkTransferDestNumber(u_short portid) { _state_data *shmp; PutLogFunID("checkTransferDestNumber"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; CutUnknownPrefix((char *)shmp->process_info.ppsService.feeTransfer.account.number); if(!strcmp((char *)shmp->caller_info.number, (char *)shmp->process_info.ppsService.feeTransfer.account.number)) { return FALSE; } if(GetAccountPos(&shmp->process_info.ppsService.feeTransfer.account)==FALSE) return FALSE; if(get_transfer_status_normal_flag()) { int status = GetAccountStatus(&shmp->process_info.ppsService.feeTransfer.account); if(status == T_NORMAL || status == T_FRESH || status == T_SUSPEND) return TRUE; else return FALSE; } return TRUE; } int transferAccountSMSProc(u_short portid) { _state_data *shmp; u_char short_message[256]; int result = 0; TRANSFER_FEE *feeTransfer; PutLogFunID("transferAccountSMSProc"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; switch(getTransferState(portid)) { case S_TRANSFER_IDLE: if(isTransferAllowed(portid) == FALSE) { SendServiceNotApplied(portid,SMS_TRANSFER,FeeTransferPosition); changeTransferState(portid,S_TRANSFER_EXIT); return SERVICE_RETURN_TO_PARENT; } result = checkTransferedPartialFee(&shmp->caller_info,1.0); if(result == CHECK_TRANSFERED_FEE_INSUFFIENT ) { SendTransferInsufficientFeeRequest(portid,SMS_TRANSFER); return SERVICE_EXIT_PPS; } changeTransferState(portid,S_WART_INPUT_DESTNUMBER); case S_WART_INPUT_DESTNUMBER: result = getTransferSMSACK(portid,short_message); switch(result) { case 0: break; case -1: return SERVICE_EXIT_PPS; break; default: short_message[result] = 0; result = getTransferInfo(portid,short_message); if(result < 0) { SendReinputTransferRequest(portid,SMS_TRANSFER); return SERVICE_EXIT_PPS; } else changeTransferState(portid,S_TRANSFER_CHECK_TRANSFERED_FEE); break; } case S_TRANSFER_CHECK_TRANSFERED_FEE: result = checkTransferedPartialFee(&shmp->caller_info,shmp->process_info.ppsService.feeTransfer.fee); switch(result) { case CHECK_TRANSFERED_FEE_INSUFFIENT: SendTransferInsufficientFeeRequest(portid,SMS_TRANSFER); return SERVICE_EXIT_PPS; break; case CHECK_TRANSFERED_FEE_EXPIERED: SendTransferExpiredAccountRequest(portid,SMS_TRANSFER); return SERVICE_EXIT_PPS; break; case CHECK_TRANSFERED_FEE_OK: default: changeTransferState(portid,S_TRANSFER_CHECK_DSTNUMBER); break; } case S_TRANSFER_CHECK_DSTNUMBER: if(checkTransferDestNumber(portid) == FALSE) { SendTransferDstNumberErrorRequest(portid,SMS_TRANSFER); return SERVICE_EXIT_PPS; } else changeTransferState(portid,S_TRANSFER_PROCESSING);/* skip confirm */ case S_TRANSFER_PROCESSING: FeeTransferTransaction(shmp); changeTransferState(portid,S_TRANSFER_EXIT); case S_TRANSFER_EXIT: clearTransferInfo(portid); return SERVICE_RETURN_TO_PARENT; break; } return SERVICE_KEEP_STATE; } int transferAccountUSSDProc(u_short portid) { _state_data *shmp; u_char ussd_data[256]={0}; int result = 0; TRANSFER_FEE *feeTransfer; PutLogFunID("transferAccountUSSDProc"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; switch(getTransferState(portid)) { case S_TRANSFER_IDLE: if(pps_get_adaptor_flag()) { changeTransferState(portid,S_USSD_FT_REST_START); break; } if(isTransferAllowed(portid) == FALSE) { SendServiceNotApplied(portid,USSD_TRANSFER,FeeTransferPosition); changeTransferState(portid,S_TRANSFER_EXIT); break; } result = checkTransferedPartialFee(&shmp->caller_info,1.0); if(result == CHECK_TRANSFERED_FEE_INSUFFIENT) { SendTransferInsufficientFeeRequest(portid,USSD_TRANSFER); return SERVICE_EXIT_PPS; } if(shmp->process_info.ussd_transfer_one_input_flag == 1) { changeTransferState(portid,S_USSD_FT_ALL_IN_ONE_INPUT); break; } clearTransferInfo(portid); SendTransferRequest(portid,USSD_TRANSFER); changeTransferState(portid,S_WART_INPUT_DESTNUMBER); break; case S_WART_INPUT_DESTNUMBER: result = getUssdACK(portid,ussd_data); switch(result) { case 0: break; case -1: return SERVICE_EXIT_PPS; break; default: result = getTransferInfo(portid,ussd_data); if(result < 0) { if(shmp->process_info.serviceInput++ >= SERVICE_INPUT_NUM) return SERVICE_EXIT_PPS; SendReinputTransferRequest(portid,USSD_TRANSFER); } else changeTransferState(portid,S_TRANSFER_CHECK_TRANSFERED_FEE); break; } break; case S_TRANSFER_CHECK_TRANSFERED_FEE: result = checkTransferedPartialFee(&shmp->caller_info,shmp->process_info.ppsService.feeTransfer.fee); switch(result) { case CHECK_TRANSFERED_FEE_INSUFFIENT: if(shmp->process_info.serviceInput++ >= SERVICE_INPUT_NUM) { return SERVICE_EXIT_PPS; } SendTransferInsufficientFeeRequest(portid,USSD_TRANSFER); changeTransferState(portid,S_WART_INPUT_DESTNUMBER); break; case CHECK_TRANSFERED_FEE_EXPIERED: SendTransferExpiredAccountRequest(portid,USSD_TRANSFER); return SERVICE_EXIT_PPS; break; case CHECK_TRANSFERED_FEE_OK: default: changeTransferState(portid,S_TRANSFER_CHECK_DSTNUMBER); break; } break; case S_TRANSFER_CHECK_DSTNUMBER: if(checkTransferDestNumber(portid) == FALSE) { if(shmp->process_info.serviceInput++ >= SERVICE_INPUT_NUM) { return SERVICE_EXIT_PPS; } SendTransferDstNumberErrorRequest(portid,USSD_TRANSFER); changeTransferState(portid,S_WART_INPUT_DESTNUMBER); } else changeTransferState(portid,S_TRANSFER_CONFIRM); break; case S_TRANSFER_CONFIRM: SendTransferInfoConfirmRequest(portid,USSD_TRANSFER); changeTransferState(portid,S_WAIT_TRANSFER_CONFIRM); break; case S_WAIT_TRANSFER_CONFIRM: result = getUssdACK(portid,ussd_data); switch(result) { case 0: break; case -1: return SERVICE_EXIT_PPS; break; default: if(result != 1) { if(shmp->process_info.serviceInput++ >= SERVICE_INPUT_NUM) return SERVICE_EXIT_PPS; else SendReinputTransferConfrimRequest(portid,USSD_TRANSFER); } result = ussd_data[0] - '0'; switch(result) { case CONFIRM_OK: changeTransferState(portid,S_TRANSFER_PROCESSING); break; case CONFIRM_ENTER_AGAIN: changeTransferState(portid,S_TRANSFER_IDLE); break; case CONFIRM_CANCEL: changeTransferState(portid,S_TRANSFER_EXIT); break; default: return SERVICE_EXIT_PPS; break; } break; } break; case S_TRANSFER_PROCESSING: FeeTransferTransaction(shmp); changeTransferState(portid,S_TRANSFER_EXIT); break; case S_USSD_FT_ALL_IN_ONE_INPUT: strcpy((char *)shmp->process_info.ppsService.feeTransfer.account.number, shmp->process_info.tmpDigits); result = WaitingForInputTransferOutAccount(shmp); if(result != INPUT_SUCCESS) { SendTransferDstNumberErrorRequest(portid,USSD_TRANSFER); changeTransferState(portid,S_TRANSFER_EXIT); break; } if(checkTransferDestNumber(portid) == FALSE) { SendTransferDstNumberErrorRequest(portid,USSD_TRANSFER); return SERVICE_EXIT_PPS; } result = checkTransferedPartialFee(&shmp->caller_info,shmp->process_info.ppsService.feeTransfer.fee); switch(result) { case CHECK_TRANSFERED_FEE_INSUFFIENT: SendTransferInsufficientFeeRequest(portid,USSD_TRANSFER); break; case CHECK_TRANSFERED_FEE_EXPIERED: SendTransferExpiredAccountRequest(portid,USSD_TRANSFER); break; case CHECK_TRANSFERED_FEE_OK: FeeTransferTransaction(shmp); default: break; } changeTransferState(portid,S_TRANSFER_EXIT); break; case S_USSD_FT_REST_START: result = pps_rest_transfer_process(portid); if(result != 0) { changeTransferState(portid,S_TRANSFER_EXIT); } break; case S_TRANSFER_EXIT: clearTransferInfo(portid); return SERVICE_EXIT_PPS; break; } return SERVICE_KEEP_STATE; } int chargeOrTransfer(u_short portid) { _state_data *shmp; int result = SERVICE_KEEP_STATE,rst; TRANSFER_FEE *feeTransfer; shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; if(shmp->process_info.funnel++>PROMPT_AND_COLLECT_TIMER) { return SERVICE_EXIT_PPS; } switch(getTransferState(portid)) { case S_TRANSFER_IDLE: clearTransferInfo(portid); changeTransferState(portid,S_WAIT_TRANSFER_CONFIRM); playPromptAndCollectVoice(portid,CHARGE_OR_TRANSFER,1); break; case S_WAIT_TRANSFER_CONFIRM: rst = WaitForChoice_chargeOrTransfer(shmp); switch(rst) { case NO_INPUT: break; case INPUT_SUCCESS: rst = getInputtedChoice(shmp); switch(rst) { case CONFIRM_OK: changeTransferState(portid,S_TRANSFER_EXIT); break; case CONFIRM_ENTER_AGAIN: changeTransferState(portid,S_TRANSFER_EXIT); break; default: result = SERVICE_EXIT_PPS; break; } break; case INPUT_ERROR_REINPUT: playPromptAndCollectVoice(portid,CHARGE_OR_TRANSFER,1); break; case INPUT_ERROR_EXIT: result = SERVICE_EXIT_PPS; break; } break; case S_TRANSFER_EXIT: result = SERVICE_RETURN_TO_PARENT; break; default: result = SERVICE_EXIT_PPS; break; } return result; } int transferAccountIVRProc(u_short portid) { _state_data *shmp; int result = SERVICE_KEEP_STATE,rst; TRANSFER_FEE *feeTransfer; PutLogFunID("transferPPSAccountProc"); shmp = (_state_data *)&smshm_ptr->state_data; shmp += portid; if(shmp->process_info.funnel++>PROMPT_AND_COLLECT_TIMER) { clearTransferInfo(portid); return SERVICE_EXIT_PPS; } switch(getTransferState(portid)) { case S_TRANSFER_IDLE: if(isTransferAllowed(portid) == FALSE) { playPromptVoice(portid,SERIVCE_NOT_APPLIED); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_ERROR); break; } rst = checkTransferedPartialFee(&shmp->caller_info,1.0); if(rst == CHECK_TRANSFERED_FEE_INSUFFIENT) { playPromptVoice(portid,TRANSFERED_FEE_INSUFFIENT); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_ERROR); return result; } clearTransferInfo(portid); changeTransferState(portid,S_INPUT_DESTNUMBER); break; case S_INPUT_DESTNUMBER: playPromptAndCollectVoice(portid,PleaseInputTransferInAccount,MAX_IVR_INPUT_LEN); changeTransferState(portid,S_WART_INPUT_DESTNUMBER); break; case S_WART_INPUT_DESTNUMBER: rst = WaitingForInputTransferOutAccount(shmp); switch(rst) { case NO_INPUT: break; case INPUT_SUCCESS: saveFirstInputtedTransferOutAccount(shmp); changeTransferState(portid,S_INPUT_DESTNUMBER_AGAIN); break; case INPUT_ERROR_REINPUT: playPromptAndCollectVoice(portid,InvalidAccountIputAgain,MAX_IVR_INPUT_LEN); break; case INPUT_ERROR_EXIT: result = SERVICE_EXIT_PPS; break; } break; case S_INPUT_DESTNUMBER_AGAIN: playPromptAndCollectVoice(portid,PleaseInputTransferInAccountAgain,MAX_IVR_INPUT_LEN); changeTransferState(portid,S_WART_INPUT_DESTNUMBER_AGAIN); break; case S_WART_INPUT_DESTNUMBER_AGAIN: rst = WaitingForInputTransferOutAccount(shmp); switch(rst) { case NO_INPUT: break; case INPUT_SUCCESS: changeTransferState(portid,S_MATCH_DESTNUMBER); break; case INPUT_ERROR_REINPUT: playPromptAndCollectVoice(portid,InvalidAccountIputAgain,MAX_IVR_INPUT_LEN); changeTransferState(portid,S_WART_INPUT_DESTNUMBER); break; case INPUT_ERROR_EXIT: result = SERVICE_EXIT_PPS; break; } break; case S_MATCH_DESTNUMBER: if(matchTwoInpuutedTransferOutAccount(shmp)) changeTransferState(portid,S_FULL_PARTIAL_TRANSFER_CHOICE); else changeTransferState(portid,S_DESTNUMBER_NOT_MATCHED); break; case S_DESTNUMBER_NOT_MATCHED: playPromptVoice(portid,NotMatchedTransferOutAccount); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_ERROR); break; case S_FULL_PARTIAL_TRANSFER_CHOICE: playPromptAndCollectVoice(portid,FULL_PARTIAL_TRANSFER_CHOICE,1); changeTransferState(portid,S_WAIT_FULL_PARTIAL_TRANSFER_CHOICE); break; case S_WAIT_FULL_PARTIAL_TRANSFER_CHOICE: rst = WaitForTransferMode(shmp); switch(rst) { case NO_INPUT: break; case INPUT_SUCCESS: rst = getInputtedChoice(shmp); if( rst == FULL_TRANSFER_MODE) { rst = checkTransferedFullFee(shmp); switch(rst) { case CHECK_TRANSFERED_FEE_OK: changeTransferState(portid,S_TRANSFER_CONFIRM); break; case CHECK_TRANSFERED_FEE_INSUFFIENT: playPromptVoice(portid,TRANSFERED_FEE_INSUFFIENT); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_ERROR); break; case CHECK_TRANSFERED_FEE_EXPIERED: default: playPromptVoice(portid,TRANSFERED_FEE_EXPIERED); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_ERROR); break; } } else if( rst == PARTIAL_TRANSFER_MODE) changeTransferState(portid,S_INPUT_FEE_TRANSFERED); else changeTransferState(portid,S_FULL_PARTIAL_TRANSFER_CHOICE); break; case INPUT_ERROR_REINPUT: playPromptAndCollectVoice(portid,FULL_PARTIAL_TRANSFER_CHOICE,1); break; case INPUT_ERROR_EXIT: result = SERVICE_EXIT_PPS; break; } break; case S_INPUT_FEE_TRANSFERED: playPromptAndCollectVoice(portid,INPUT_FEE_TRANSFERED,MAX_FEE_LENGTH); changeTransferState(portid,S_WAIT_INPUT_FEE_TRANSFERED); break; case S_WAIT_INPUT_FEE_TRANSFERED: rst = WaitingForInputTransferOutFee(shmp); switch(rst) { case NO_INPUT: break; case INPUT_SUCCESS: rst = checkTransferedPartialFee(&shmp->caller_info,shmp->process_info.ppsService.feeTransfer.fee); switch(rst) { case CHECK_TRANSFERED_FEE_OK: changeTransferState(portid,S_TRANSFER_CONFIRM); break; case CHECK_TRANSFERED_FEE_INSUFFIENT: playPromptVoice(portid,TRANSFERED_FEE_INSUFFIENT); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_ERROR); break; case CHECK_TRANSFERED_FEE_EXPIERED: default: playPromptVoice(portid,TRANSFERED_FEE_EXPIERED); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_ERROR); break; } break; case INPUT_ERROR_REINPUT: playPromptAndCollectVoice(portid,INPUT_FEE_TRANSFERED_FORMAT_ERROR,MAX_IVR_INPUT_LEN); break; case INPUT_ERROR_EXIT: result = SERVICE_EXIT_PPS; break; } break; case S_TRANSFER_CONFIRM: SendTransferInfoPromptToSrf(portid); changeTransferState(portid,S_PLAY_TRANSFER_CONFIRM_SUCCESS); break; case S_PLAY_TRANSFER_CONFIRM_SUCCESS: rst = CallingCardWaitingForSpecialResourceReport(shmp); if(rst == SERVICE_KEEP_STATE) break; else if(rst == 1) { playPromptAndCollectVoice(portid,CONFIRM_LISTEN_AGAIN,1); changeTransferState(portid,S_WAIT_TRANSFER_CONFIRM); } else result = SERVICE_EXIT_PPS; break; case S_WAIT_TRANSFER_CONFIRM: rst = WaitForChoice(shmp); switch(rst) { case NO_INPUT: break; case INPUT_SUCCESS: rst = getInputtedChoice(shmp); switch(rst) { case CONFIRM_OK: changeTransferState(portid,S_TRANSFER_PROCESSING); break; case CONFIRM_ENTER_AGAIN: changeTransferState(portid,S_FULL_PARTIAL_TRANSFER_CHOICE); break; case CONFIRM_LISTEN_RE: changeTransferState(portid,S_TRANSFER_CONFIRM); break; case CONFIRM_CANCEL: default: changeTransferState(portid,S_TRANSFER_EXIT); break; } break; case INPUT_ERROR_REINPUT: playPromptAndCollectVoice(portid,CONFIRM_LISTEN_AGAIN,1); break; case INPUT_ERROR_EXIT: result = SERVICE_EXIT_PPS; break; } break; case S_TRANSFER_PROCESSING: FeeTransferTransaction(shmp); playPromptVoice(portid,TransferSuccess); changeTransferState(portid,S_PLAY_TRANSFERED_FEE_SUCCESS); break; case S_PLAY_TRANSFERED_FEE_SUCCESS: rst = CallingCardWaitingForSpecialResourceReport(shmp); if(rst == SERVICE_KEEP_STATE) break; else if(rst == 1) { changeTransferState(portid,S_TRANSFER_EXIT); } else result = SERVICE_EXIT_PPS; break; case S_PLAY_TRANSFERED_FEE_ERROR: rst = CallingCardWaitingForSpecialResourceReport(shmp); if(rst == SERVICE_KEEP_STATE) break; else if(rst == 1) { changeTransferState(portid,S_TRANSFER_EXIT); } else result = SERVICE_EXIT_PPS; break; case S_TRANSFER_EXIT: clearTransferInfo(portid); result = SERVICE_RETURN_TO_PARENT; break; default: clearTransferInfo(portid); result = SERVICE_EXIT_PPS; break; } return result; }