Taebu / prq

prq.co.kr
MIT License
1 stars 1 forks source link

prq적립 cid point #132

Closed Taebu closed 4 years ago

Taebu commented 4 years ago

처리과정

  1. PC 에 설치된 톡톡클릭으로 부터 콜로그가 발생하거나 프린터가 출력이 된다면 두가지의 모든 경우의 한하여 콜로그를 발생시켜 prq 서버에 전송한다. 단 핸드폰 번호만 전송하고 중복은 전송하지 아니한다.
CREATE TABLE `cdr` (
  `date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `UserID` varchar(255) NOT NULL DEFAULT '',
  `port` varchar(10) DEFAULT '0',
  `callerid` varchar(30) NOT NULL DEFAULT '',
  `calledid` varchar(30) DEFAULT '',
  `state` tinyint(1) DEFAULT '0',
  `comname` varchar(5) DEFAULT 'COM1' COMMENT 'com 포트 구분'
) ENGINE=MyISAM DEFAULT CHARSET=utf8
  1. prq 서버 175.126.111.21 에 callerid 디비에 cdr에 기록된다.

after insert Trigger를 작동하는데 이름은 cdr_inserted 이다. 계략적인 간단한 소스는 아래와 같다.

CREATE DEFINER=`root`@`123.142.52.92` TRIGGER cdr_inserted AFTER INSERT ON callerid.cdr FOR EACH ROW
BEGIN

-- 2. 핸드폰 번호인지?
SET @ishp=IF(substr(NEW.callerid,1,2)='01',true,false);
-- 3. kt port 인가? (0번 포트)
SET @iskt=IF(NEW.port=0,true,false);

-- 4. 상점 정보 조회  

select
    st_name,st_tel_1,st_hp_1,st_no,st_status,st_ata_YN
INTO
    @st_name,@st_tel,@st_hp,@st_no,@st_status,@st_ata_YN
FROM
    prq.prq_store 
WHERE
    st_port=NEW.port and mb_id=NEW.UserID limit 1;
-- 5. 매장이 @st_ata_YN='Y' 
IF(@st_ata_YN='Y')THEN
    -- 5-1. 매장 번호로 `prq`.`prq_ata_pay` 데이터를 조회한다. 
    /* ATA_PAY_LOG */
    select
     ap_status,ap_autobill_YN,ap_autobill_date,ap_reserve,ap_limit,ap_limit_cnt,ap_no,bp_appid,bt_code
    INTO
     @ap_status,@ap_autobill_YN,@ap_autobill_date,@ap_reserve,@ap_limit,@ap_limit_cnt,@ap_no,@bp_appid,@bt_code
     from prq.prq_ata_pay where st_no=@st_no and ap_status='join' limit 1;

    -- 5-2. 예약시간을 분으로 변경하여 변경한 만큼 더하여, 시스템 데이터에 더한다. 
    SELECT DATE_ADD(SYSDATE(), INTERVAL @ap_reserve MINUTE) INTO @date_client_req;

    -- 5-3. 가입상태인가?
    SET @IS_ATA_JOIN=IF(@ap_status='join',true,false);

    -- 5-4. 정기결재 인가?
    SET @IS_AUTOBILL_YN=IF(@ap_autobill_YN='Y',true,false);

    -- 5-5. 정기 결제가 아니라 일시결제인경우 지난 여부 측정
    -- 안지났으면 true인 1, 지났으면 false인 0 
    SET @IS_LAST_ATA=(select date_add(@ap_autobill_date,interval 1 month)>=date(sysdate()));

    -- 5-5-1. @IS_LAST_ATA=false 지난 경우 prq.prq_store.st_ata_YN='N' 만료 상태 자동 변경
    IF(@IS_LAST_ATA=false) THEN
        update prq.prq_store set st_ata_YN='N' where st_no=@st_no;
    END IF;

    -- 5-6. 상태가 조인 5-3. 과 겹쳠
    SET @IS_ATA_SEND=IF(@ap_status="join",true,false);

    -- 5-7. @
    /* 가입 상태이고 정기 결제 라면 */
    IF(@IS_ATA_JOIN=true AND @IS_AUTOBILL_YN=true) THEN

    -- 5-7-1. 알림톡 발신 대기로 만듦.
    -- 알림톡 발신 대기
    insert into prq.prq_ata_log set 
     `date_client_req`=@date_client_req,
     `at_ismms`='false',
     `at_receiver`=NEW.callerid,
     `at_sender`=NEW.calledid,
     `at_date`=date(now()),
     `at_month_cnt`=@ap_limit_cnt,
     `at_month_limit`=@ap_limit,
     `bp_appid`=@bp_appid,
     `bt_code`=@bt_code,
     `st_no`=@st_no,
     `at_status`='1',
     `at_result`='',
     `ap_no`=@ap_no,
     `at_datetime`=now();

    -- 5-7-2. 가입상태이고, 일시결재 이며, 기간이 안 지났을 때 알림톡 발생 
    /* 가입 상태이고 일시 결제 라면 기간이 안지났으면 */
    ELSEIF(@IS_ATA_JOIN=true AND @IS_AUTOBILL_YN=false AND @IS_LAST_ATA=true) THEN
    -- 일시 결제
    insert into prq.prq_ata_log set 
      `date_client_req`=@date_client_req,
      `at_ismms`='false',
      `at_receiver`=NEW.callerid,
      `at_sender`=NEW.calledid,
      `at_date`=date(now()),
      `at_month_cnt`=@ap_limit_cnt,
      `at_month_limit`=@ap_limit,
      `bp_appid`=@bp_appid,
      `bt_code`=@bt_code,
      `st_no`=@st_no,
      `at_status`='1',
      `at_result`='',
      `ap_no`=@ap_no,
      `at_datetime`=now();

    END IF;

/* 알림톡이 아닌 경우 와 상점 상태에 따른 대기,해지,설치 실패 처리 여부*/
-- wa 31(대기)
ELSEIF (@st_status='wa') THEN
INSERT INTO prq.prq_cdr_tmp SET 
cd_date=NEW.date,
cd_id=NEW.UserID,
cd_state='31',
cd_callerid=NEW.callerid,
cd_port=NEW.port;

-- ca 32(설치실패)
ELSEIF (@st_status='ca') THEN
INSERT INTO prq.prq_cdr_tmp SET 
cd_date=NEW.date,
cd_id=NEW.UserID,
cd_state='32',
cd_callerid=NEW.callerid,
cd_port=NEW.port;

-- tm 33 (해지)
ELSEIF (@st_status='tm') THEN
INSERT INTO prq.prq_cdr_tmp SET 
cd_date=NEW.date,
cd_id=NEW.UserID,
cd_state='33',
cd_callerid=NEW.callerid,
cd_port=NEW.port;

/* 알림톡이 아닌 경우 처리중,  */
/* 1.KT port 핸드폰 전화인 경우  */
ELSEIF (@iskt AND @ishp) THEN

INSERT INTO prq.prq_cdr SET 
cd_date=NEW.date,
cd_id=NEW.UserID,
cd_port=NEW.port,
cd_callerid=NEW.callerid,
cd_calledid=NEW.calledid;

/* 2. CID 핸드폰 전화인 경우  */
ELSEIF (@iskt=false AND @ishp) THEN

INSERT INTO prq.prq_cdr SET 
cd_date=NEW.date,
cd_id=NEW.UserID,
cd_port=NEW.port,
cd_callerid=NEW.callerid,
cd_name=@st_name,
cd_tel=@st_tel,
cd_hp=@st_hp;

/* 3. KT 일반전화인 경우 */
ELSEIF (@iskt AND @ishp=false) THEN

INSERT INTO prq.prq_cdr SET 
cd_date=NEW.date,
cd_id=NEW.UserID,
cd_port=NEW.port,
cd_callerid=NEW.callerid,
cd_calledid=NEW.calledid;

/* 4. CID 일반전화인 경우 */
ELSEIF (@iskt=false AND @ishp=false) THEN

INSERT INTO prq.prq_cdr_tmp SET 
cd_date=NEW.date,
cd_id=NEW.UserID,
cd_port=NEW.port,
cd_callerid=NEW.callerid,
cd_name=@st_name,
cd_state='2',
cd_tel=@st_tel,
cd_hp=@st_hp;

END IF;
/* IF (NEW.port=0 AND @ishp) THEN */

END
  1. prq.prq_cdr 에 입력 된 것을 처리하는 kr.co.prq.prq_cdr에 구동 된다.

3-1.

Taebu commented 4 years ago

자바 프로그램 kr.co.cashq.PRQ_CDR 분석

  1. prq.prq_cdr에서 cd_state가 0인 것을 cd_date 내림차순으로 15단위로 조회한다.
  2. 시스템 시작 시간을 Milliscond로 조회하여 startTime에 담는다.
  3. 1의 쿼리를 합쳐 prq 디비에 담아 실행한다.
  4. black_list에 수신 거부 목록을 불러온다.
  5. prq 디비에 연결 조회된 갯수 만큼 반복한다. 5-1. PRQ_CDR.heart_beat에 1을 담는다. 5-2. hist_table에 prq.prq_cdr_YYYYMM 형태의 로그 테이블을 조회하고, hist_table에 조회된 로그 테이블 명을 담는다.(없으면 테이블을 생성한다.) 5-3. 조회한 prq_cdr.cd_callerid가 핸돈 패턴인지 검사하여 is_hp에 해당하는 결과를 담는다. 5-4. prq_cdr.cd_date를 dateitme 형식으로 조정하여 cd_date변수에 담는다. 5-5. prq_cdr에 해당하는 모든 column_name을 변수명에 해당하는 내용을 담는다. 5-6. 일반번호인 경우 !is_hp 5-6-1. 상태를 prq.prq_cdr.cd_state를 "2"로 변경한다. 5-6-2. 5.에 해당하는 반복에서 다음 쿼리를 처리하도록 continue를 실행한다. 5-7. cd_port가 "0"인 경우
    • cd_port가 "0"이면 kt포트를 사용한다. cd_id가 cd_calledid로 get_store_kt정보를 조회한다. 5-7-1. 조회된 prq_store 정보는 "st_no, st_name, st_mno, st_tel_1, st_hp_1, st_thumb_paper, st_top_msg, st_middle_msg, st_bottom_msg, st_modoo_url, st_vtel 의 10개 정보를 배열에 담는다. 조회된 상점정보가 없으면 150으로 정보 배열에 담는다. 5-7-2. 조회된 정보를 각각 st_no, cd_hp, cd_tel에 담는다. 5-7-3. cd_name, cd_tel, cd_hp정보를 prq_cdr에 갱신한다. 5-8. cd_port가 "0"이 아니면 5-8-1. cd_id, cd_port로 get_store하여 store_info에 배열에 담는다. 5-8-2. st_no에 store_info[0]에 정보를 담는다. 5-9. is_shophp 에 store_info[4]에 해당하는 st_hp_1에 정보가 행드폰 번호인지를 판별하여 결과를 담는다. 5-10. 만약 is_shophp가 핸드폰 번호가 아니라면, 5-10-1. cd_state가 "6"으로 하여, cdr을 갱신하ㄷ 5-10-2. 5.에 해당하는 반복에서 다음 쿼리를 처리하도록 continue를 실행한다 5-11. store_info[1]이 "150" 초기값이면, 5-11-1. cd_state를 5로 설정. "업소누락"으로 표기하고 cdr을 갱신한다. 5-11-2. 5.에 해당하는 반복에서 다음 쿼리를 처리하도록 continue를 실행한다 5-12. cd_hp가 공백이라면 5-12-1. cd_state를 "6"으로 하여, cdr을 갱신한다. 5-12-2. 5.에 해당하는 반복에서 다음 쿼리를 처리하도록 continue를 실행한다 5-13. cd_date,cd_tel,cd_hp,cd_callerid로 지난 콜로그 처리된 prq.prq_cdr_tmp테이블에 입력된 시간을 비교하는 mysql함수인지를 판별하여 last_cdr 변수에 담는다. 단, 값이 없으면 처음으로 간주하여 "first_sent" 값으로 담는다. 5-14. cd_hp로 get_mno_limit함수를 호출 s[0] = mn_mms_limit (mms 일일전송건수) s[1] = mn_dup_limit (mms 전송제한일수) 를 조회한다. 값이 없으면, s[0]은 150, s[1]은 7을 리턴한다. 결과는 mno_limit (array)에 담는다. 5-15. cd_hp로 get_send_cnt 함수를 호출하여 day_cnt 변수에 담는다.
    • prq_sf_log에 ms_hp로 ms_date에 해당하는 ms_success column 결과를 as cnt 하여 조회 결과를 return한다. 5-16. cd_hp로 get_mms_daily함수를 호출하여 mno_devicice_daily(int)변수에 담는다.
    • prq.prq_mms_log에 mm_sender를 cd_hp로 조회하고, mm_datetime이 오늘인것의 mm_datetime이 desc 최신순으로 하나를 조회하는데 mm_daily_cnt를 조회한다. 단! 아무 값이 없으면 0을 리턴한다. 5-17. mno_limit 배열 String을 Integer.parseInt로 형변환하여 mn_mms_limit, mn_dup_limit 인 (Int)변수에 각각 담는다. 5-18. prq_cdr에 cd_date, cd_tel, cd_hp로 조회하여 set_cdr 함수화 cd_day_limit, cd_device_day_cnt, cd_day_cnt 수정 5-19. day_cnt를 cd_day_cnt에 담는다. 5-20. mm_daily_cnt 와 cd_day_cnt 와 cd_device_day_cnt를 더하여 my_device_cnt에 담는다. 5-21. my_device_cnt와 mn_mms_limit를 비교해 초과여부를 is_set_limit 변수에 담는다. 5-22. 만약 is_set_limit가 true이면, 5-22-1. 결과를 "150건 초과"로 설정하고 prq_cdr.cd_state를 "4"로 설정한다. 5-22-2. 5.를 다시 실행하도록 스킵한다. continue 실행. 5-23. 만약 last_cdr이 "first_sent"이면, 5-23-1. chk_limit_date를 "처음보냄"이라 정의 5-23-2. 아니라면 5-23-2-1. last_cdr을 int로 변경하여 chk_cd_date에 담는다. 5-23-2-2. mn_dup_limit와 chk_cd_date를 비교해 mn_dup_limit가 크다면 "보내면 안됨" 작다면 "보냄"이라고 chk_limit_date에 담는다. 5-24. chk_mms = true 선언 5-25. st_bottom_msg, st_modoo_url, store_info를 담아 chg_mms_msg함수를 호출합니다. 그리고 message에 담는다.
    • 상점 prq_store에 통신사, 블로그 홍보여부의 메시지를 담아 리턴한다. 5-26. 상점 썸네일 정보를 호출하여 st_thumb_paper에서 "http://prq.co.kr/prq/uploads/TH/"+st_thumb_paper를 img_url에 담는다. 5-27. daily_mms_cnt= 0으로 선언한다. 5-28. daily_mms_cnt와 cd_day_cnt더하고 daily_mms_cnt에 담는다. 5-29. result_msg 에 last+"/"+mn_dup_limit+"일 발송"으로 담는다. 5-30. 만약 last_cdr이 "first_sent"라면 5-30-1. result_msg에 "처음발송 /"+mn_dup_limit 5-30-2. chk_mms를 true로 선언한다. 5-31. prq.prq_store.st_no 에 코드가 5008인것을 조회 Y면 true를 아니면 false를 is_cid_point에 담는다. 5-32. is_cid_point와 is_hp가 참이면 5-32-1. 매장에 5009코드를 조회해 code_5009에 담는다. (시아이디포인트 적립금액) 5-32-2. cashq.biz_code 매장에 code_5010을 조회하여 담는다. 5-32-3. biz_code에 code_5010결과를 담는다. 5-32-4. store.seq 에 해당하는 5011 코드 결과를 code_5011jc ufzhgsuf. 5-32-5. end_dt에 cd_datew에서20초를 더한 datetime형식으로 담는다. 5-32-6. called_hangup_dt에 cd_date에서 7초를 더하여 datetime형식으로 담는다. 5-32-7. conn_edt에 cd_date를 20초 더하여 datetime형식으로 담는다. 5-32-8. service_sdt 에 cd_date를 7초 더하여 datetime 형식으로 담는다. 5-32-9. service_edt 에 conn_edt를 담는다. 5-32-10. unique_id에 cd_date를 unixtime으로 변경하여 담는다. 5-32-11. 위의 모든 값을 cidpoint_info MAP에 담아 set_cidpoint_log에 담아 실행합니다. prq서버와 cashq 서버 각각에 디비에 담습니다. prq.prq_cidpoint_log에 기록됩니다. 이중화 디비사용!!! 5-33. chk_mms가 참이면, is_hp 참, is_release 참일때 5-33-1. message, st_no, store_info[6], cd_callerid, cd_hp, store_info[5], false를 담아, 함수 set_gcmurl을 실행합니다. *http://prq.co.kr/prq/set_gcm.php을 실행(POST) 5-34. cdr_info 배열에 정보를 담아 prq_cdr.cd_state를 "1"로 갱신한다. 5-35. get_happycall()함수를 실행해서 happy_log에 담는다.
  6. 반복이끝난다.
  7. SQLExepction이 일어나면 "ErrPOS001"이 기록된다.
  8. Exepction이 일어나면 "ErrPOS002"이 기록된다.
  9. finally마지막으로, prq디비 연결을 닫는다. 9-1. 시스템 밀리세컨드를 담아 endTime에 담는다. 9-2. set_hist() 함수를 실행한다. cd_state가 0초과인 모든 prq_cdr을 prq_cdr_tmp에 조회하여 담는다. 마지막으로 del_hist()함수를 실행해 cd_state가 0 이상인 prq_cdr을 지운다.
  10. ### 소요시간(초.0f) : " + ( endTime-startTime)/ 1000.0f+:초"") : 하여 시스템에 출력한다.
  11. 끝낸다.
Taebu commented 4 years ago

소스상에 문제가 아니라 캐시큐 접속에러가 있었음. PRQ_CDR.java Line 26

    /**
     * 메인프로세스
     */
    private static void doMainProcess() {
        Thread this_thread = Thread.currentThread();
        try {
            synchronized (this_thread) {
                while (doWork()) {
                    if (0 < heart_beat++) {
                        if (DBConn.getConnection() != null) {

를 아래와 같이 Cashq도 연결하도록 변경 Line 26

    /**
     * 메인프로세스
     */
    private static void doMainProcess() {
        Thread this_thread = Thread.currentThread();
        try {
            synchronized (this_thread) {
                while (doWork()) {
                    if (0 < heart_beat++) {
                        if (DBConn.getConnection() != null||DBConnCashq.getConnection()!=null) {